1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
 
   3  * Copyright (c) 2005-2009 Apple Inc. All rights reserved.
 
   5  * @APPLE_LICENSE_HEADER_START@
 
   7  * This file contains Original Code and/or Modifications of Original Code
 
   8  * as defined in and that are subject to the Apple Public Source License
 
   9  * Version 2.0 (the 'License'). You may not use this file except in
 
  10  * compliance with the License. Please obtain a copy of the License at
 
  11  * http://www.opensource.apple.com/apsl/ and read it before using this
 
  14  * The Original Code and all software distributed under the License are
 
  15  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 
  16  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 
  17  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 
  18  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 
  19  * Please see the License for the specific language governing rights and
 
  20  * limitations under the License.
 
  22  * @APPLE_LICENSE_HEADER_END@
 
  25 #ifndef __EXECUTABLE_MACH_O__
 
  26 #define __EXECUTABLE_MACH_O__
 
  32 #include <uuid/uuid.h>
 
  33 #include <mach/i386/thread_status.h>
 
  34 #include <mach/ppc/thread_status.h>
 
  35 #include <CommonCrypto/CommonDigest.h>
 
  41 #include <ext/hash_map>
 
  43 #include "ObjectFile.h"
 
  44 #include "ExecutableFile.h"
 
  47 #include "MachOFileAbstraction.hpp"
 
  48 #include "MachOTrie.hpp"
 
  53 //      To implement architecture xxx, you must write template specializations for the following methods:
 
  54 //                      MachHeaderAtom<xxx>::setHeaderInfo()
 
  55 //                      ThreadsLoadCommandsAtom<xxx>::getSize()
 
  56 //                      ThreadsLoadCommandsAtom<xxx>::copyRawContent()
 
  57 //                      Writer<xxx>::addObjectRelocs()
 
  58 //                      Writer<xxx>::fixUpReferenceRelocatable()
 
  59 //                      Writer<xxx>::fixUpReferenceFinal()
 
  60 //                      Writer<xxx>::stubableReference()
 
  61 //                      Writer<xxx>::weakImportReferenceKind()
 
  62 //                      Writer<xxx>::GOTReferenceKind()
 
  67 namespace executable {
 
  70 template <typename A> class WriterAtom;
 
  71 template <typename A> class PageZeroAtom;
 
  72 template <typename A> class CustomStackAtom;
 
  73 template <typename A> class MachHeaderAtom;
 
  74 template <typename A> class SegmentLoadCommandsAtom;
 
  75 template <typename A> class EncryptionLoadCommandsAtom;
 
  76 template <typename A> class SymbolTableLoadCommandsAtom;
 
  77 template <typename A> class DyldInfoLoadCommandsAtom;
 
  78 template <typename A> class ThreadsLoadCommandsAtom;
 
  79 template <typename A> class DylibIDLoadCommandsAtom;
 
  80 template <typename A> class RoutinesLoadCommandsAtom;
 
  81 template <typename A> class DyldLoadCommandsAtom;
 
  82 template <typename A> class UUIDLoadCommandAtom;
 
  83 template <typename A> class LinkEditAtom;
 
  84 template <typename A> class SectionRelocationsLinkEditAtom;
 
  85 template <typename A> class CompressedRebaseInfoLinkEditAtom;
 
  86 template <typename A> class CompressedBindingInfoLinkEditAtom;
 
  87 template <typename A> class CompressedWeakBindingInfoLinkEditAtom;
 
  88 template <typename A> class CompressedLazyBindingInfoLinkEditAtom;
 
  89 template <typename A> class CompressedExportInfoLinkEditAtom;
 
  90 template <typename A> class LocalRelocationsLinkEditAtom;
 
  91 template <typename A> class ExternalRelocationsLinkEditAtom;
 
  92 template <typename A> class SymbolTableLinkEditAtom;
 
  93 template <typename A> class SegmentSplitInfoLoadCommandsAtom;
 
  94 template <typename A> class SegmentSplitInfoContentAtom;
 
  95 template <typename A> class IndirectTableLinkEditAtom;
 
  96 template <typename A> class ModuleInfoLinkEditAtom;
 
  97 template <typename A> class StringsLinkEditAtom;
 
  98 template <typename A> class LoadCommandsPaddingAtom;
 
  99 template <typename A> class UnwindInfoAtom;
 
 100 template <typename A> class StubAtom;
 
 101 template <typename A> class StubHelperAtom;
 
 102 template <typename A> class ClassicStubHelperAtom;
 
 103 template <typename A> class HybridStubHelperAtom;
 
 104 template <typename A> class HybridStubHelperHelperAtom;
 
 105 template <typename A> class FastStubHelperAtom;
 
 106 template <typename A> class FastStubHelperHelperAtom;
 
 107 template <typename A> class LazyPointerAtom;
 
 108 template <typename A> class NonLazyPointerAtom;
 
 109 template <typename A> class DylibLoadCommandsAtom;
 
 110 template <typename A> class BranchIslandAtom;
 
 113 // SectionInfo should be nested inside Writer, but I can't figure out how to make the type accessible to the Atom classes
 
 114 class SectionInfo : public ObjectFile::Section {
 
 116                                                                                 SectionInfo() : fFileOffset(0), fSize(0), fRelocCount(0), fRelocOffset(0), 
 
 117                                                                                                                 fIndirectSymbolOffset(0), fAlignment(0), fAllLazyPointers(false), 
 
 118                                                                                                                 fAllLazyDylibPointers(false),fAllNonLazyPointers(false), fAllStubs(false),
 
 119                                                                                                                 fAllSelfModifyingStubs(false), fAllStubHelpers(false),
 
 120                                                                                                                 fAllZeroFill(false), fVirtualSection(false),
 
 121                                                                                                                 fHasTextLocalRelocs(false), fHasTextExternalRelocs(false)
 
 122                                                                                                                 { fSegmentName[0] = '\0'; fSectionName[0] = '\0'; }
 
 123         void                                                            setIndex(unsigned int index) { fIndex=index; }
 
 124         std::vector<ObjectFile::Atom*>          fAtoms;
 
 125         char                                                            fSegmentName[20];
 
 126         char                                                            fSectionName[20];
 
 127         uint64_t                                                        fFileOffset;
 
 129         uint32_t                                                        fRelocCount;
 
 130         uint32_t                                                        fRelocOffset;
 
 131         uint32_t                                                        fIndirectSymbolOffset;
 
 133         bool                                                            fAllLazyPointers;
 
 134         bool                                                            fAllLazyDylibPointers;
 
 135         bool                                                            fAllNonLazyPointers;
 
 137         bool                                                            fAllSelfModifyingStubs;
 
 138         bool                                                            fAllStubHelpers;
 
 140         bool                                                            fVirtualSection;
 
 141         bool                                                            fHasTextLocalRelocs;
 
 142         bool                                                            fHasTextExternalRelocs;
 
 145 // SegmentInfo should be nested inside Writer, but I can't figure out how to make the type accessible to the Atom classes
 
 149                                                                                 SegmentInfo(uint64_t pageSize) : fInitProtection(0), fMaxProtection(0), fFileOffset(0), fFileSize(0),
 
 150                                                                                                                 fBaseAddress(0), fSize(0), fPageSize(pageSize), fFixedAddress(false), 
 
 151                                                                                                                 fIndependentAddress(false), fHasLoadCommand(true) { fName[0] = '\0'; }
 
 152         std::vector<class SectionInfo*>         fSections;
 
 154         uint32_t                                                        fInitProtection;
 
 155         uint32_t                                                        fMaxProtection;
 
 156         uint64_t                                                        fFileOffset;
 
 158         uint64_t                                                        fBaseAddress;
 
 162         bool                                                            fIndependentAddress;
 
 163         bool                                                            fHasLoadCommand;
 
 168                                         RebaseInfo(uint8_t t, uint64_t addr) : fType(t), fAddress(addr) {}
 
 172         int operator<(const RebaseInfo& rhs) const {
 
 173                 // sort by type, then address
 
 174                 if ( this->fType != rhs.fType )
 
 175                         return  (this->fType < rhs.fType );
 
 176                 return  (this->fAddress < rhs.fAddress );
 
 181                                         BindingInfo(uint8_t t, int ord, const char* sym, bool weak_import, uint64_t addr, int64_t addend) 
 
 182                                                 : fType(t), fFlags(weak_import ? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0 ), fLibraryOrdinal(ord), 
 
 183                                                         fSymbolName(sym), fAddress(addr), fAddend(addend) {}
 
 184                                         BindingInfo(uint8_t t, const char* sym, bool non_weak_definition, uint64_t addr, int64_t addend) 
 
 185                                                 : fType(t), fFlags(non_weak_definition ? BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION : 0 ), fLibraryOrdinal(0), 
 
 186                                                         fSymbolName(sym), fAddress(addr), fAddend(addend) {}
 
 190         const char*             fSymbolName;
 
 195         int operator<(const BindingInfo& rhs) const {
 
 196                 // sort by library, symbol, type, then address
 
 197                 if ( this->fLibraryOrdinal != rhs.fLibraryOrdinal )
 
 198                         return  (this->fLibraryOrdinal < rhs.fLibraryOrdinal );
 
 199                 if ( this->fSymbolName != rhs.fSymbolName )
 
 200                         return ( strcmp(this->fSymbolName, rhs.fSymbolName) < 0 );
 
 201                 if ( this->fType != rhs.fType )
 
 202                         return  (this->fType < rhs.fType );
 
 203                 return  (this->fAddress < rhs.fAddress );
 
 210         std::vector<uint8_t>            fData;
 
 212         std::vector<uint8_t>& bytes() { return fData; }
 
 213         unsigned long size() const { return fData.size(); }
 
 214         void reserve(unsigned long l) { fData.reserve(l); }
 
 215         const uint8_t* start() const { return &fData[0]; }
 
 217         void append_uleb128(uint64_t value) {
 
 224                         fData.push_back(byte);
 
 226                 } while( byte >= 0x80 );
 
 229         void append_sleb128(int64_t value) {
 
 230                 bool isNeg = ( value < 0 );
 
 237                                 more = ( (value != -1) || ((byte & 0x40) == 0) );
 
 239                                 more = ( (value != 0) || ((byte & 0x40) != 0) );
 
 242                         fData.push_back(byte);
 
 247         void append_string(const char* str) {
 
 248                 for (const char* s = str; *s != '\0'; ++s)
 
 250                 fData.push_back('\0');
 
 253         void append_byte(uint8_t byte) {
 
 254                 fData.push_back(byte);
 
 257         static unsigned int     uleb128_size(uint64_t value) {
 
 262                 } while ( value != 0 );
 
 266         void pad_to_size(unsigned int alignment) {
 
 267                 while ( (fData.size() % alignment) != 0 )
 
 273 template <typename A>
 
 274 class Writer : public ExecutableFile::Writer
 
 277         Writer(const char* path, Options& options, std::vector<ExecutableFile::DyLibUsed>& dynamicLibraries);
 
 280         virtual const char*                                                             getPath()                                                               { return fFilePath; }
 
 281         virtual time_t                                                                  getModificationTime()                                   { return 0; }
 
 282         virtual DebugInfoKind                                                   getDebugInfoKind()                                              { return ObjectFile::Reader::kDebugInfoNone; }
 
 283         virtual std::vector<class ObjectFile::Atom*>&   getAtoms()                                                              { return fWriterSynthesizedAtoms; }
 
 284         virtual std::vector<class ObjectFile::Atom*>*   getJustInTimeAtomsFor(const char* name) { return NULL; }
 
 285         virtual std::vector<Stab>*                                              getStabs()                                                              { return NULL; }
 
 287         virtual ObjectFile::Atom&                                               makeObjcInfoAtom(ObjectFile::Reader::ObjcConstraint objcContraint, 
 
 288                                                                                                                                                 bool objcReplacementClasses);
 
 289         virtual class ObjectFile::Atom*                                 getUndefinedProxyAtom(const char* name);
 
 290         virtual void                                                                    addSynthesizedAtoms(const std::vector<class ObjectFile::Atom*>& existingAtoms,
 
 291                                                                                                                                                   class ObjectFile::Atom* dyldClassicHelperAtom,
 
 292                                                                                                                                                   class ObjectFile::Atom* dyldCompressedHelperAtom,
 
 293                                                                                                                                                   class ObjectFile::Atom* dyldLazyDylibHelperAtom,
 
 294                                                                                                                                                         bool biggerThanTwoGigs,
 
 295                                                                                                                                                         uint32_t dylibSymbolCount,
 
 296                                                                                                                                                         std::vector<class ObjectFile::Atom*>& newAtoms);
 
 297         virtual uint64_t                                                                write(std::vector<class ObjectFile::Atom*>& atoms,
 
 298                                                                                                                   std::vector<class ObjectFile::Reader::Stab>& stabs,
 
 299                                                                                                                   class ObjectFile::Atom* entryPointAtom,
 
 300                                                                                                                   bool createUUID, bool canScatter,
 
 301                                                                                                                   ObjectFile::Reader::CpuConstraint cpuConstraint,
 
 302                                                                                                                   std::set<const class ObjectFile::Atom*>& atomsThatOverrideWeak,
 
 303                                                                                                                   bool hasExternalWeakDefinitions);
 
 306         typedef typename A::P                   P;
 
 307         typedef typename A::P::uint_t   pint_t;
 
 309         enum RelocKind { kRelocNone, kRelocInternal, kRelocExternal };
 
 311         void                                            assignFileOffsets();
 
 312         void                                            synthesizeStubs(const std::vector<class ObjectFile::Atom*>& existingAtoms,
 
 313                                                                                                         std::vector<class ObjectFile::Atom*>& newAtoms);
 
 314         void                                            synthesizeKextGOT(const std::vector<class ObjectFile::Atom*>& existingAtoms,
 
 315                                                                         std::vector<class ObjectFile::Atom*>& newAtoms);
 
 316         void                                            createSplitSegContent();
 
 317         void                                            synthesizeUnwindInfoTable();
 
 318         void                                            insertDummyStubs();
 
 319         void                                            partitionIntoSections();
 
 320         bool                                            addBranchIslands();
 
 321         bool                                            createBranchIslands();
 
 322         bool                                            isBranchThatMightNeedIsland(uint8_t kind);
 
 323         uint32_t                                        textSizeWhenMightNeedBranchIslands();
 
 324         uint32_t                                        maxDistanceBetweenIslands(); 
 
 325         void                                            adjustLoadCommandsAndPadding();
 
 326         void                                            createDynamicLinkerCommand();
 
 327         void                                            createDylibCommands();
 
 328         void                                            buildLinkEdit();
 
 329         const char*                                     getArchString();
 
 331         uint64_t                                        writeAtoms();
 
 332         void                                            writeNoOps(int fd, uint32_t from, uint32_t to);
 
 333         void                                            copyNoOps(uint8_t* from, uint8_t* to);
 
 334         bool                                            segmentsCanSplitApart(const ObjectFile::Atom& from, const ObjectFile::Atom& to);
 
 335         void                                            addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref);
 
 336         void                                            collectExportedAndImportedAndLocalAtoms();
 
 337         void                                            setNlistRange(std::vector<class ObjectFile::Atom*>& atoms, uint32_t startIndex, uint32_t count);
 
 338         void                                            addLocalLabel(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* name);
 
 339         void                                            addGlobalLabel(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* name);
 
 340         void                                            buildSymbolTable();
 
 341         bool                                            stringsNeedLabelsInObjects();
 
 342         const char*                                     symbolTableName(const ObjectFile::Atom* atom);
 
 343         void                                            setExportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry);
 
 344         void                                            setImportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry);
 
 345         void                                            setLocalNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry);
 
 346         void                                            copyNlistRange(const std::vector<macho_nlist<P> >& entries, uint32_t startIndex);
 
 347         uint64_t                                        getAtomLoadAddress(const ObjectFile::Atom* atom);
 
 348         uint8_t                                         ordinalForLibrary(ObjectFile::Reader* file);
 
 349         bool                                            targetRequiresWeakBinding(const ObjectFile::Atom& target);
 
 350         int                                                     compressedOrdinalForImortedAtom(ObjectFile::Atom* target);
 
 351         bool                                            shouldExport(const ObjectFile::Atom& atom) const;
 
 353         void                                            adjustLinkEditSections();
 
 354         void                                            buildObjectFileFixups();
 
 355         void                                            buildExecutableFixups();
 
 356         bool                                            preboundLazyPointerType(uint8_t* type);
 
 357         uint64_t                                        relocAddressInFinalLinkedImage(uint64_t address, const ObjectFile::Atom* atom) const;
 
 358         void                                            fixUpReferenceFinal(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const;
 
 359         void                                            fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const;
 
 360         void                                            fixUpReference_powerpc(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom,
 
 361                                                                                                                 uint8_t buffer[], bool finalLinkedImage) const;
 
 362         uint32_t                                        symbolIndex(ObjectFile::Atom& atom);
 
 363         bool                                            makesExternalRelocatableReference(ObjectFile::Atom& target) const;
 
 364         uint32_t                                        addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref);
 
 365         uint32_t                                        addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::Reference* ref);
 
 366         uint8_t                                         getRelocPointerSize();
 
 367         uint64_t                                        maxAddress();
 
 368         bool                                            stubableReference(const ObjectFile::Atom* inAtom, const ObjectFile::Reference* ref);
 
 369         bool                                            GOTReferenceKind(uint8_t kind);
 
 370         bool                                            optimizableGOTReferenceKind(uint8_t kind);
 
 371         bool                                            weakImportReferenceKind(uint8_t kind);
 
 372         unsigned int                            collectStabs();
 
 373         uint64_t                                        valueForStab(const ObjectFile::Reader::Stab& stab);
 
 374         uint32_t                                        stringOffsetForStab(const ObjectFile::Reader::Stab& stab);
 
 375         uint8_t                                         sectionIndexForStab(const ObjectFile::Reader::Stab& stab);
 
 376         void                                            addStabs(uint32_t startIndex);
 
 377         RelocKind                                       relocationNeededInFinalLinkedImage(const ObjectFile::Atom& target) const;
 
 378         bool                                            illegalRelocInFinalLinkedImage(const ObjectFile::Reference&);
 
 379         bool                                            generatesLocalTextReloc(const ObjectFile::Reference&, const ObjectFile::Atom& atom, SectionInfo* curSection);
 
 380         bool                                            generatesExternalTextReloc(const ObjectFile::Reference&, const ObjectFile::Atom& atom, SectionInfo* curSection);
 
 381         bool                                            mightNeedPadSegment();
 
 382         void                                            scanForAbsoluteReferences();
 
 383         bool                                            needsModuleTable();
 
 384         void                                            optimizeDylibReferences();
 
 385         bool                                            indirectSymbolInRelocatableIsLocal(const ObjectFile::Reference* ref) const;
 
 387         struct DirectLibrary {
 
 388                 class ObjectFile::Reader*       fLibrary;
 
 393         friend class WriterAtom<A>;
 
 394         friend class PageZeroAtom<A>;
 
 395         friend class CustomStackAtom<A>;
 
 396         friend class MachHeaderAtom<A>;
 
 397         friend class SegmentLoadCommandsAtom<A>;
 
 398         friend class EncryptionLoadCommandsAtom<A>;
 
 399         friend class SymbolTableLoadCommandsAtom<A>;
 
 400         friend class DyldInfoLoadCommandsAtom<A>;
 
 401         friend class ThreadsLoadCommandsAtom<A>;
 
 402         friend class DylibIDLoadCommandsAtom<A>;
 
 403         friend class RoutinesLoadCommandsAtom<A>;
 
 404         friend class DyldLoadCommandsAtom<A>;
 
 405         friend class UUIDLoadCommandAtom<A>;
 
 406         friend class LinkEditAtom<A>;
 
 407         friend class SectionRelocationsLinkEditAtom<A>;
 
 408         friend class CompressedRebaseInfoLinkEditAtom<A>;
 
 409         friend class CompressedBindingInfoLinkEditAtom<A>;
 
 410         friend class CompressedWeakBindingInfoLinkEditAtom<A>;
 
 411         friend class CompressedLazyBindingInfoLinkEditAtom<A>;
 
 412         friend class CompressedExportInfoLinkEditAtom<A>;
 
 413         friend class LocalRelocationsLinkEditAtom<A>;
 
 414         friend class ExternalRelocationsLinkEditAtom<A>;
 
 415         friend class SymbolTableLinkEditAtom<A>;
 
 416         friend class SegmentSplitInfoLoadCommandsAtom<A>;
 
 417         friend class SegmentSplitInfoContentAtom<A>;
 
 418         friend class IndirectTableLinkEditAtom<A>;
 
 419         friend class ModuleInfoLinkEditAtom<A>;
 
 420         friend class StringsLinkEditAtom<A>;
 
 421         friend class LoadCommandsPaddingAtom<A>;
 
 422         friend class UnwindInfoAtom<A>;
 
 423         friend class StubAtom<A>;
 
 424         friend class StubHelperAtom<A>;
 
 425         friend class ClassicStubHelperAtom<A>;
 
 426         friend class HybridStubHelperAtom<A>;
 
 427         friend class FastStubHelperAtom<A>;
 
 428         friend class FastStubHelperHelperAtom<A>;
 
 429         friend class HybridStubHelperHelperAtom<A>;
 
 430         friend class LazyPointerAtom<A>;
 
 431         friend class NonLazyPointerAtom<A>;
 
 432         friend class DylibLoadCommandsAtom<A>;
 
 433         friend class BranchIslandAtom<A>;
 
 435         const char*                                                                             fFilePath;
 
 437         std::vector<class ObjectFile::Atom*>*                   fAllAtoms;
 
 438         std::vector<class ObjectFile::Reader::Stab>*    fStabs;
 
 439         std::set<const class ObjectFile::Atom*>*                fRegularDefAtomsThatOverrideADylibsWeakDef;
 
 440         class SectionInfo*                                                              fLoadCommandsSection;
 
 441         class SegmentInfo*                                                              fLoadCommandsSegment;
 
 442         class MachHeaderAtom<A>*                                                fMachHeaderAtom;
 
 443         class EncryptionLoadCommandsAtom<A>*                    fEncryptionLoadCommand;
 
 444         class SegmentLoadCommandsAtom<A>*                               fSegmentCommands;
 
 445         class SymbolTableLoadCommandsAtom<A>*                   fSymbolTableCommands;
 
 446         class LoadCommandsPaddingAtom<A>*                               fHeaderPadding;
 
 447         class UnwindInfoAtom<A>*                                                fUnwindInfoAtom;
 
 448         class UUIDLoadCommandAtom<A>*                               fUUIDAtom;
 
 449         std::vector<class ObjectFile::Atom*>                    fWriterSynthesizedAtoms;
 
 450         std::vector<SegmentInfo*>                                               fSegmentInfos;
 
 451         class SegmentInfo*                                                              fPadSegmentInfo;
 
 452         class ObjectFile::Atom*                                                 fEntryPoint;
 
 453         class ObjectFile::Atom*                                                 fDyldClassicHelperAtom;
 
 454         class ObjectFile::Atom*                                                 fDyldCompressedHelperAtom;
 
 455         class ObjectFile::Atom*                                                 fDyldLazyDylibHelper;
 
 456         std::map<class ObjectFile::Reader*, DylibLoadCommandsAtom<A>*>  fLibraryToLoadCommand;
 
 457         std::map<class ObjectFile::Reader*, uint32_t>   fLibraryToOrdinal;
 
 458         std::map<class ObjectFile::Reader*, class ObjectFile::Reader*>  fLibraryAliases;
 
 459         std::set<class ObjectFile::Reader*>                             fForcedWeakImportReaders;
 
 460         std::vector<class ObjectFile::Atom*>                    fExportedAtoms;
 
 461         std::vector<class ObjectFile::Atom*>                    fImportedAtoms;
 
 462         std::vector<class ObjectFile::Atom*>                    fLocalSymbolAtoms;
 
 463         std::vector<macho_nlist<P> >                                    fLocalExtraLabels;
 
 464         std::vector<macho_nlist<P> >                                    fGlobalExtraLabels;
 
 465         std::map<ObjectFile::Atom*, uint32_t>                   fAtomToSymbolIndex;
 
 466         class SectionRelocationsLinkEditAtom<A>*                fSectionRelocationsAtom;        
 
 467         class CompressedRebaseInfoLinkEditAtom<A>*              fCompressedRebaseInfoAtom;
 
 468         class CompressedBindingInfoLinkEditAtom<A>*             fCompressedBindingInfoAtom;
 
 469         class CompressedWeakBindingInfoLinkEditAtom<A>* fCompressedWeakBindingInfoAtom;
 
 470         class CompressedLazyBindingInfoLinkEditAtom<A>* fCompressedLazyBindingInfoAtom;
 
 471         class CompressedExportInfoLinkEditAtom<A>*              fCompressedExportInfoAtom;
 
 472         class LocalRelocationsLinkEditAtom<A>*                  fLocalRelocationsAtom;
 
 473         class ExternalRelocationsLinkEditAtom<A>*               fExternalRelocationsAtom;
 
 474         class SymbolTableLinkEditAtom<A>*                               fSymbolTableAtom;
 
 475         class SegmentSplitInfoContentAtom<A>*                   fSplitCodeToDataContentAtom;
 
 476         class IndirectTableLinkEditAtom<A>*                             fIndirectTableAtom;
 
 477         class ModuleInfoLinkEditAtom<A>*                                fModuleInfoAtom;
 
 478         class StringsLinkEditAtom<A>*                                   fStringsAtom;
 
 479         class PageZeroAtom<A>*                                                  fPageZeroAtom;
 
 480         class NonLazyPointerAtom<A>*                                    fFastStubGOTAtom;
 
 481         macho_nlist<P>*                                                                 fSymbolTable;
 
 482         std::vector<macho_relocation_info<P> >                  fSectionRelocs;
 
 483         std::vector<macho_relocation_info<P> >                  fInternalRelocs;
 
 484         std::vector<macho_relocation_info<P> >                  fExternalRelocs;
 
 485         std::vector<RebaseInfo>                                                 fRebaseInfo;
 
 486         std::vector<BindingInfo>                                                fBindingInfo;
 
 487         std::vector<BindingInfo>                                                fWeakBindingInfo;
 
 488         std::map<const ObjectFile::Atom*,ObjectFile::Atom*>     fStubsMap;
 
 489         std::map<ObjectFile::Atom*,ObjectFile::Atom*>   fGOTMap;
 
 490         std::vector<class StubAtom<A>*>                                 fAllSynthesizedStubs;
 
 491         std::vector<ObjectFile::Atom*>                                  fAllSynthesizedStubHelpers;
 
 492         std::vector<class LazyPointerAtom<A>*>                  fAllSynthesizedLazyPointers;
 
 493         std::vector<class LazyPointerAtom<A>*>                  fAllSynthesizedLazyDylibPointers;
 
 494         std::vector<class NonLazyPointerAtom<A>*>               fAllSynthesizedNonLazyPointers;
 
 495         uint32_t                                                                                fSymbolTableCount;
 
 496         uint32_t                                                                                fSymbolTableStabsCount;
 
 497         uint32_t                                                                                fSymbolTableStabsStartIndex;
 
 498         uint32_t                                                                                fSymbolTableLocalCount;
 
 499         uint32_t                                                                                fSymbolTableLocalStartIndex;
 
 500         uint32_t                                                                                fSymbolTableExportCount;
 
 501         uint32_t                                                                                fSymbolTableExportStartIndex;
 
 502         uint32_t                                                                                fSymbolTableImportCount;
 
 503         uint32_t                                                                                fSymbolTableImportStartIndex;
 
 504         uint32_t                                                                                fLargestAtomSize;
 
 505         uint32_t                                                                                fDylibSymbolCountUpperBound;
 
 506         bool                                                                                    fEmitVirtualSections;
 
 507         bool                                                                                    fHasWeakExports;
 
 508         bool                                                                                    fReferencesWeakImports;
 
 510         bool                                                                                    fWritableSegmentPastFirst4GB;
 
 511         bool                                                                                    fNoReExportedDylibs;
 
 512         bool                                                                                    fBiggerThanTwoGigs;
 
 514         bool                                                                                    fHasThumbBranches;
 
 515         std::map<const ObjectFile::Atom*,bool>                  fWeakImportMap;
 
 516         std::set<const ObjectFile::Reader*>                             fDylibReadersWithNonWeakImports;
 
 517         std::set<const ObjectFile::Reader*>                             fDylibReadersWithWeakImports;
 
 518         SegmentInfo*                                                                    fFirstWritableSegment;
 
 519         ObjectFile::Reader::CpuConstraint                               fCpuConstraint;
 
 520         uint32_t                                                                                fAnonNameIndex;
 
 524 class Segment : public ObjectFile::Segment
 
 527                                                                 Segment(const char* name, bool readable, bool writable, bool executable, bool fixedAddress)
 
 528                                                                                          : fName(name), fReadable(readable), fWritable(writable), fExecutable(executable), fFixedAddress(fixedAddress) {}
 
 529         virtual const char*                     getName() const                                 { return fName; }
 
 530         virtual bool                            isContentReadable() const               { return fReadable; }
 
 531         virtual bool                            isContentWritable() const               { return fWritable; }
 
 532         virtual bool                            isContentExecutable() const             { return fExecutable; }
 
 533         virtual bool                            hasFixedAddress() const                 { return fFixedAddress; }
 
 535         static Segment                                                          fgTextSegment;
 
 536         static Segment                                                          fgPageZeroSegment;
 
 537         static Segment                                                          fgLinkEditSegment;
 
 538         static Segment                                                          fgStackSegment;
 
 539         static Segment                                                          fgImportSegment;
 
 540         static Segment                                                          fgROImportSegment;
 
 541         static Segment                                                          fgDataSegment;
 
 542         static Segment                                                          fgObjCSegment;
 
 543         static Segment                                                          fgHeaderSegment;
 
 548         const bool                                      fReadable;
 
 549         const bool                                      fWritable;
 
 550         const bool                                      fExecutable;
 
 551         const bool                                      fFixedAddress;
 
 554 Segment         Segment::fgPageZeroSegment("__PAGEZERO", false, false, false, true);
 
 555 Segment         Segment::fgTextSegment("__TEXT", true, false, true, false);
 
 556 Segment         Segment::fgLinkEditSegment("__LINKEDIT", true, false, false, false);
 
 557 Segment         Segment::fgStackSegment("__UNIXSTACK", true, true, false, true);
 
 558 Segment         Segment::fgImportSegment("__IMPORT", true, true, true, false);
 
 559 Segment         Segment::fgROImportSegment("__IMPORT", true, false, true, false);
 
 560 Segment         Segment::fgDataSegment("__DATA", true, true, false, false);
 
 561 Segment         Segment::fgObjCSegment("__OBJC", true, true, false, false);
 
 562 Segment         Segment::fgHeaderSegment("__HEADER", true, false, true, false);
 
 565 template <typename A>
 
 566 class WriterAtom : public ObjectFile::Atom
 
 569         enum Kind { zeropage, machHeaderApp, machHeaderDylib, machHeaderBundle, machHeaderObject, loadCommands, undefinedProxy };
 
 570                                                                                         WriterAtom(Writer<A>& writer, Segment& segment) : fWriter(writer), fSegment(segment) { }
 
 572         virtual ObjectFile::Reader*                             getFile() const                                 { return &fWriter; }
 
 573         virtual bool                                                    getTranslationUnitSource(const char** dir, const char** name) const { return false; }
 
 574         virtual const char*                                             getName() const                                 { return NULL; }
 
 575         virtual const char*                                             getDisplayName() const                  { return this->getName(); }
 
 576         virtual Scope                                                   getScope() const                                { return ObjectFile::Atom::scopeTranslationUnit; }
 
 577         virtual DefinitionKind                                  getDefinitionKind() const               { return kRegularDefinition; }
 
 578         virtual SymbolTableInclusion                    getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableNotIn; }
 
 579         virtual bool                                                    dontDeadStrip() const                   { return true; }
 
 580         virtual bool                                                    isZeroFill() const                              { return false; }
 
 581         virtual bool                                                    isThumb() const                                 { return false; }
 
 582         virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return fgEmptyReferenceList; }
 
 583         virtual bool                                                    mustRemainInSection() const             { return true; }
 
 584         virtual ObjectFile::Segment&                    getSegment() const                              { return fSegment; }
 
 585         virtual ObjectFile::Atom&                               getFollowOnAtom() const                 { return *((ObjectFile::Atom*)NULL); }
 
 586         virtual uint32_t                                                getOrdinal() const                              { return 0; }
 
 587         virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                     { return NULL; }
 
 588         virtual ObjectFile::Alignment                   getAlignment() const                    { return ObjectFile::Alignment(2); }
 
 589         virtual void                                                    copyRawContent(uint8_t buffer[]) const { throw "don't use copyRawContent"; }
 
 590         virtual void                                                    setScope(Scope)                                 { }
 
 594         virtual                                                                 ~WriterAtom() {}
 
 595         typedef typename A::P                                   P;
 
 596         typedef typename A::P::E                                E;
 
 598         static Segment&                 headerSegment(Writer<A>& writer) { return (writer.fOptions.outputKind()==Options::kPreload)
 
 599                                                                                                                                         ? Segment::fgHeaderSegment : Segment::fgTextSegment; }
 
 601         static std::vector<ObjectFile::Reference*>      fgEmptyReferenceList;
 
 607 template <typename A> std::vector<ObjectFile::Reference*>       WriterAtom<A>::fgEmptyReferenceList;
 
 610 template <typename A>
 
 611 class PageZeroAtom : public WriterAtom<A>
 
 614                                                                                         PageZeroAtom(Writer<A>& writer) : WriterAtom<A>(writer, Segment::fgPageZeroSegment),
 
 615                                                                                                                                                         fSize(fWriter.fOptions.zeroPageSize()) {}
 
 616         virtual const char*                                             getDisplayName() const  { return "page zero content"; }
 
 617         virtual bool                                                    isZeroFill() const              { return true; }
 
 618         virtual uint64_t                                                getSize() const                 { return fSize; }
 
 619         virtual const char*                                             getSectionName() const  { return "._zeropage"; }
 
 620         virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(12); }
 
 621         void                                                                    setSize(uint64_t size)  { fSize = size; }
 
 623         using WriterAtom<A>::fWriter;
 
 624         typedef typename A::P                                   P;
 
 629 template <typename A>
 
 630 class DsoHandleAtom : public WriterAtom<A>
 
 633                                                                                                         DsoHandleAtom(Writer<A>& writer) : WriterAtom<A>(writer, Segment::fgTextSegment) {}
 
 634         virtual const char*                                                             getName() const                         { return "___dso_handle"; }
 
 635         virtual ObjectFile::Atom::Scope                                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
 
 636         virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableNotIn; }
 
 637         virtual uint64_t                                                                getSize() const                         { return 0; }
 
 638         virtual ObjectFile::Alignment                                   getAlignment() const            { return ObjectFile::Alignment(12); }
 
 639         virtual const char*                                                             getSectionName() const          { return "._mach_header"; }
 
 640         virtual void                                                                    copyRawContent(uint8_t buffer[]) const {}
 
 644 template <typename A>
 
 645 class MachHeaderAtom : public WriterAtom<A>
 
 648                                                                                                         MachHeaderAtom(Writer<A>& writer) : WriterAtom<A>(writer, headerSegment(writer)) {}
 
 649         virtual const char*                                                             getName() const;
 
 650         virtual const char*                                                             getDisplayName() const;
 
 651         virtual ObjectFile::Atom::Scope                                 getScope() const;
 
 652         virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const;
 
 653         virtual uint64_t                                                                getSize() const                         { return sizeof(macho_header<typename A::P>); }
 
 654         virtual ObjectFile::Alignment                                   getAlignment() const            { return ObjectFile::Alignment(12); }
 
 655         virtual const char*                                                             getSectionName() const          { return "._mach_header"; }
 
 656         virtual uint32_t                                                                getOrdinal() const                      { return 1; }
 
 657         virtual void                                                                    copyRawContent(uint8_t buffer[]) const;
 
 659         using WriterAtom<A>::fWriter;
 
 660         typedef typename A::P                                   P;
 
 661         void                                                                    setHeaderInfo(macho_header<typename A::P>& header) const;
 
 664 template <typename A>
 
 665 class CustomStackAtom : public WriterAtom<A>
 
 668                                                                                         CustomStackAtom(Writer<A>& writer);
 
 669         virtual const char*                                             getDisplayName() const  { return "custom stack content"; }
 
 670         virtual bool                                                    isZeroFill() const              { return true; }
 
 671         virtual uint64_t                                                getSize() const                 { return fWriter.fOptions.customStackSize(); }
 
 672         virtual const char*                                             getSectionName() const  { return "._stack"; }
 
 673         virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(12); }
 
 675         using WriterAtom<A>::fWriter;
 
 676         typedef typename A::P                                   P;
 
 677         static bool                                                             stackGrowsDown();
 
 680 template <typename A>
 
 681 class LoadCommandAtom : public WriterAtom<A>
 
 684                                                                                         LoadCommandAtom(Writer<A>& writer) : WriterAtom<A>(writer, headerSegment(writer)), fOrdinal(fgCurrentOrdinal++) {}
 
 685         virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(log2(sizeof(typename A::P::uint_t))); }
 
 686         virtual const char*                                             getSectionName() const  { return "._load_commands"; }
 
 687         virtual uint32_t                                                getOrdinal() const              { return fOrdinal; }
 
 688         static uint64_t                                                 alignedSize(uint64_t size);
 
 691         static uint32_t                                                 fgCurrentOrdinal;
 
 694 template <typename A> uint32_t LoadCommandAtom<A>::fgCurrentOrdinal = 0;
 
 696 template <typename A>
 
 697 class SegmentLoadCommandsAtom : public LoadCommandAtom<A>
 
 700                                                                                         SegmentLoadCommandsAtom(Writer<A>& writer)  
 
 701                                                                                                 : LoadCommandAtom<A>(writer), fCommandCount(0), fSize(0) 
 
 702                                                                                                 { writer.fSegmentCommands = this; }
 
 703         virtual const char*                                             getDisplayName() const  { return "segment load commands"; }
 
 704         virtual uint64_t                                                getSize() const                 { return fSize; }
 
 705         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 709         unsigned int                                                    commandCount()                  { return fCommandCount; }
 
 711         using WriterAtom<A>::fWriter;
 
 712         typedef typename A::P                                   P;
 
 713         unsigned int                                                    fCommandCount;
 
 718 template <typename A>
 
 719 class SymbolTableLoadCommandsAtom : public LoadCommandAtom<A>
 
 722                                                                                         SymbolTableLoadCommandsAtom(Writer<A>&);
 
 723         virtual const char*                                             getDisplayName() const { return "symbol table load commands"; }
 
 724         virtual uint64_t                                                getSize() const;
 
 725         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 726         unsigned int                                                    commandCount();
 
 727                         void                                                    needDynamicTable();
 
 729         using WriterAtom<A>::fWriter;
 
 730         typedef typename A::P                                   P;
 
 731         bool                                                                    fNeedsDynamicSymbolTable;
 
 732         macho_symtab_command<typename A::P>             fSymbolTable;
 
 733         macho_dysymtab_command<typename A::P>   fDynamicSymbolTable;
 
 736 template <typename A>
 
 737 class ThreadsLoadCommandsAtom : public LoadCommandAtom<A>
 
 740                                                                                         ThreadsLoadCommandsAtom(Writer<A>& writer) 
 
 741                                                                                                 : LoadCommandAtom<A>(writer) {}
 
 742         virtual const char*                                             getDisplayName() const { return "thread load commands"; }
 
 743         virtual uint64_t                                                getSize() const;
 
 744         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 746         using WriterAtom<A>::fWriter;
 
 747         typedef typename A::P                                   P;
 
 749         uint32_t                                                                fBufferSize;
 
 752 template <typename A>
 
 753 class DyldLoadCommandsAtom : public LoadCommandAtom<A>
 
 756                                                                                         DyldLoadCommandsAtom(Writer<A>& writer)  : LoadCommandAtom<A>(writer) {}
 
 757         virtual const char*                                             getDisplayName() const  { return "dyld load command"; }
 
 758         virtual uint64_t                                                getSize() const;
 
 759         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 761         using WriterAtom<A>::fWriter;
 
 762         typedef typename A::P                                   P;
 
 765 template <typename A>
 
 766 class SegmentSplitInfoLoadCommandsAtom : public LoadCommandAtom<A>
 
 769                                                                                         SegmentSplitInfoLoadCommandsAtom(Writer<A>& writer)  : LoadCommandAtom<A>(writer) {}
 
 770         virtual const char*                                             getDisplayName() const  { return "segment split info load command"; }
 
 771         virtual uint64_t                                                getSize() const;
 
 772         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 774         using WriterAtom<A>::fWriter;
 
 775         typedef typename A::P                                   P;
 
 778 template <typename A>
 
 779 class AllowableClientLoadCommandsAtom : public LoadCommandAtom<A>
 
 782         AllowableClientLoadCommandsAtom(Writer<A>& writer, const char* client)  :
 
 783                 LoadCommandAtom<A>(writer), clientString(client) {}
 
 784         virtual const char*                                                     getDisplayName() const  { return "allowable_client load command"; }
 
 785         virtual uint64_t                                                        getSize() const;
 
 786         virtual void                                                            copyRawContent(uint8_t buffer[]) const;
 
 788         using WriterAtom<A>::fWriter;
 
 789         typedef typename A::P                                           P;
 
 790         const char*                                                                     clientString;
 
 793 template <typename A>
 
 794 class DylibLoadCommandsAtom : public LoadCommandAtom<A>
 
 797                                                                                         DylibLoadCommandsAtom(Writer<A>& writer, ExecutableFile::DyLibUsed& info) 
 
 798                                                                                          : LoadCommandAtom<A>(writer), fInfo(info), 
 
 799                                                                                                 fOptimizedAway(false) { if (fInfo.options.fLazyLoad) this->fOrdinal += 256; }
 
 800         virtual const char*                                             getDisplayName() const  { return "dylib load command"; }
 
 801         virtual uint64_t                                                getSize() const;
 
 802         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 803         virtual void                                                    optimizeAway() { fOptimizedAway = true; }
 
 804                         bool                                                    linkedWeak() { return fInfo.options.fWeakImport; }
 
 806         using WriterAtom<A>::fWriter;
 
 807         typedef typename A::P                                   P;
 
 808         ExecutableFile::DyLibUsed                               fInfo;
 
 812 template <typename A>
 
 813 class DylibIDLoadCommandsAtom : public LoadCommandAtom<A>
 
 816                                                                                         DylibIDLoadCommandsAtom(Writer<A>& writer) : LoadCommandAtom<A>(writer) {}
 
 817         virtual const char*                                             getDisplayName() const { return "dylib ID load command"; }
 
 818         virtual uint64_t                                                getSize() const;
 
 819         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 821         using WriterAtom<A>::fWriter;
 
 822         typedef typename A::P                                   P;
 
 825 template <typename A>
 
 826 class RoutinesLoadCommandsAtom : public LoadCommandAtom<A>
 
 829                                                                                         RoutinesLoadCommandsAtom(Writer<A>& writer) : LoadCommandAtom<A>(writer) {}
 
 830         virtual const char*                                             getDisplayName() const { return "routines load command"; }
 
 831         virtual uint64_t                                                getSize() const                 { return sizeof(macho_routines_command<typename A::P>); }
 
 832         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 834         using WriterAtom<A>::fWriter;
 
 835         typedef typename A::P                                   P;
 
 838 template <typename A>
 
 839 class SubUmbrellaLoadCommandsAtom : public LoadCommandAtom<A>
 
 842                                                                                         SubUmbrellaLoadCommandsAtom(Writer<A>& writer, const char* name) 
 
 843                                                                                          : LoadCommandAtom<A>(writer), fName(name) {}
 
 844         virtual const char*                                             getDisplayName() const  { return "sub-umbrella load command"; }
 
 845         virtual uint64_t                                                getSize() const;
 
 846         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 848         typedef typename A::P                                   P;
 
 852 template <typename A>
 
 853 class SubLibraryLoadCommandsAtom : public LoadCommandAtom<A>
 
 856                                                                                         SubLibraryLoadCommandsAtom(Writer<A>& writer,  const char* nameStart, int nameLen)
 
 857                                                                                                 : LoadCommandAtom<A>(writer), fNameStart(nameStart), fNameLength(nameLen) {}
 
 858         virtual const char*                                             getDisplayName() const  { return "sub-library load command"; }
 
 859         virtual uint64_t                                                getSize() const;
 
 860         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 862         using WriterAtom<A>::fWriter;
 
 863         typedef typename A::P                                   P;
 
 864         const char*                                                             fNameStart;
 
 868 template <typename A>
 
 869 class UmbrellaLoadCommandsAtom : public LoadCommandAtom<A>
 
 872                                                                                         UmbrellaLoadCommandsAtom(Writer<A>& writer, const char* name)
 
 873                                                                                                         : LoadCommandAtom<A>(writer), fName(name) {}
 
 874         virtual const char*                                             getDisplayName() const  { return "umbrella load command"; }
 
 875         virtual uint64_t                                                getSize() const;
 
 876         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 878         using WriterAtom<A>::fWriter;
 
 879         typedef typename A::P                                   P;
 
 883 template <typename A>
 
 884 class UUIDLoadCommandAtom : public LoadCommandAtom<A>
 
 887                                                                                         UUIDLoadCommandAtom(Writer<A>& writer)
 
 888                                                                                                 : LoadCommandAtom<A>(writer), fEmit(false) {}
 
 889         virtual const char*                                             getDisplayName() const  { return "uuid load command"; }
 
 890         virtual uint64_t                                                getSize() const                 { return fEmit ? sizeof(macho_uuid_command<typename A::P>) : 0; }
 
 891         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 892         virtual void                                                generate();
 
 893                         void                                                setContent(const uint8_t uuid[16]);
 
 894                         const uint8_t*                                  getUUID()                               { return fUUID; }
 
 896         using WriterAtom<A>::fWriter;
 
 897         typedef typename A::P                                   P;
 
 903 template <typename A>
 
 904 class RPathLoadCommandsAtom : public LoadCommandAtom<A>
 
 907                                                                                         RPathLoadCommandsAtom(Writer<A>& writer, const char* path)
 
 908                                                                                                 : LoadCommandAtom<A>(writer), fPath(path) {}
 
 909         virtual const char*                                             getDisplayName() const  { return "rpath load command"; }
 
 910         virtual uint64_t                                                getSize() const;
 
 911         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 913         using WriterAtom<A>::fWriter;
 
 914         typedef typename A::P                                   P;
 
 918 template <typename A>
 
 919 class EncryptionLoadCommandsAtom : public LoadCommandAtom<A>
 
 922                                                                                         EncryptionLoadCommandsAtom(Writer<A>& writer)
 
 923                                                                                                 : LoadCommandAtom<A>(writer), fStartOffset(0),
 
 925         virtual const char*                                             getDisplayName() const  { return "encryption info load command"; }
 
 926         virtual uint64_t                                                getSize() const { return sizeof(macho_encryption_info_command<typename A::P>); }
 
 927         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 928         void                                                                    setStartEncryptionOffset(uint32_t off) { fStartOffset = off; }
 
 929         void                                                                    setEndEncryptionOffset(uint32_t off) { fEndOffset = off; }
 
 931         using WriterAtom<A>::fWriter;
 
 932         typedef typename A::P                                   P;
 
 933         uint32_t                                                                fStartOffset;
 
 937 template <typename A>
 
 938 class DyldInfoLoadCommandsAtom : public LoadCommandAtom<A>
 
 941                                                                                         DyldInfoLoadCommandsAtom(Writer<A>& writer)
 
 942                                                                                                 : LoadCommandAtom<A>(writer) {}
 
 943         virtual const char*                                             getDisplayName() const  { return "dyld info load command"; }
 
 944         virtual uint64_t                                                getSize() const { return sizeof(macho_dyld_info_command<typename A::P>); }
 
 945         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 947         using WriterAtom<A>::fWriter;
 
 948         typedef typename A::P                                   P;
 
 952 template <typename A>
 
 953 class LoadCommandsPaddingAtom : public WriterAtom<A>
 
 956                                                                                         LoadCommandsPaddingAtom(Writer<A>& writer)
 
 957                                                                                                         : WriterAtom<A>(writer, headerSegment(writer)), fSize(0) {}
 
 958         virtual const char*                                             getDisplayName() const  { return "header padding"; }
 
 959         virtual uint64_t                                                getSize() const                 { return fSize; }
 
 960         virtual const char*                                             getSectionName() const  { return "._load_cmds_pad"; }
 
 961         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 963         void                                                                    setSize(uint64_t newSize);
 
 965         using WriterAtom<A>::fWriter;
 
 966         typedef typename A::P                                   P;
 
 970 template <typename A>
 
 971 class UnwindInfoAtom : public WriterAtom<A>
 
 974                                                                                                         UnwindInfoAtom(Writer<A>& writer) : WriterAtom<A>(writer, Segment::fgTextSegment), 
 
 975                                                                                                                                                                                 fHeaderSize(0), fPagesSize(0), fAlignment(4) {}
 
 976         virtual const char*                                                             getName() const                         { return "unwind info"; }
 
 977         virtual ObjectFile::Atom::Scope                                 getScope() const                        { return ObjectFile::Atom::scopeTranslationUnit; }
 
 978         virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableNotIn; }
 
 979         virtual uint64_t                                                                getSize() const                         { return fHeaderSize+fPagesSize; }
 
 980         virtual ObjectFile::Alignment                                   getAlignment() const            { return fAlignment; }
 
 981         virtual const char*                                                             getSectionName() const          { return "__unwind_info"; }
 
 982         virtual uint32_t                                                                getOrdinal() const                      { return 1; }
 
 983         virtual std::vector<ObjectFile::Reference*>&    getReferences() const           { return (std::vector<ObjectFile::Reference*>&)fReferences; }
 
 984         virtual void                                                                    copyRawContent(uint8_t buffer[]) const;
 
 986         void                                                                                    addUnwindInfo(ObjectFile::Atom* func, uint32_t offset, uint32_t encoding, 
 
 987                                                                                                                         ObjectFile::Reference* fdeRef, ObjectFile::Reference* lsda,
 
 988                                                                                                                          ObjectFile::Atom* personalityPointer);
 
 992         using WriterAtom<A>::fWriter;
 
 993         typedef typename A::P                                   P;
 
 994         struct Info { ObjectFile::Atom* func; ObjectFile::Atom* fde; ObjectFile::Atom* lsda; uint32_t lsdaOffset; ObjectFile::Atom* personalityPointer; uint32_t encoding; };
 
 995         struct LSDAEntry { ObjectFile::Atom* func; ObjectFile::Atom* lsda; uint32_t lsdaOffset; };
 
 996         struct RegFixUp { uint8_t* contentPointer; ObjectFile::Atom* func; ObjectFile::Atom* fde; };
 
 997         struct CompressedFixUp { uint8_t* contentPointer; ObjectFile::Atom* func; ObjectFile::Atom* fromFunc; };
 
 998         struct CompressedEncodingFixUp { uint8_t* contentPointer; ObjectFile::Atom* fde; };
 
1000         bool                            encodingMeansUseDwarf(compact_unwind_encoding_t encoding);
 
1001         void                            compressDuplicates(std::vector<Info>& uniqueInfos);
 
1002         void                            findCommonEncoding(const std::vector<Info>& uniqueInfos, std::map<uint32_t, unsigned int>& commonEncodings);
 
1003         void                            makeLsdaIndex(const std::vector<Info>& uniqueInfos, std::map<ObjectFile::Atom*, uint32_t>& lsdaIndexOffsetMap);
 
1004         unsigned int            makeRegularSecondLevelPage(const std::vector<Info>& uniqueInfos, uint32_t pageSize, unsigned int endIndex, 
 
1006         unsigned int            makeCompressedSecondLevelPage(const std::vector<Info>& uniqueInfos,   
 
1007                                                                                                                 const std::map<uint32_t,unsigned int> commonEncodings,  
 
1008                                                                                                                 uint32_t pageSize, unsigned int endIndex, uint8_t*& pageEnd);
 
1009         void                            makePersonalityIndex(std::vector<Info>& uniqueInfos);
 
1012         uint32_t                                                                fHeaderSize;
 
1013         uint32_t                                                                fPagesSize;
 
1014         uint8_t*                                                                fHeaderContent;
 
1015         uint8_t*                                                                fPagesContent;
 
1016         uint8_t*                                                                fPagesContentForDelete;
 
1017         ObjectFile::Alignment                                   fAlignment;
 
1018         std::vector<Info>                                               fInfos;
 
1019         std::map<ObjectFile::Atom*, uint32_t>   fPersonalityIndexMap;
 
1020         std::vector<LSDAEntry>                                  fLSDAIndex;
 
1021         std::vector<RegFixUp>                                   fRegFixUps;
 
1022         std::vector<CompressedFixUp>                    fCompressedFixUps;
 
1023         std::vector<CompressedEncodingFixUp>    fCompressedEncodingFixUps;
 
1024         std::vector<ObjectFile::Reference*>             fReferences;
 
1029 template <typename A>
 
1030 class LinkEditAtom : public WriterAtom<A>
 
1033                                                                                         LinkEditAtom(Writer<A>& writer) : WriterAtom<A>(writer, Segment::fgLinkEditSegment), fOrdinal(fgCurrentOrdinal++) {}
 
1034         uint64_t                                                                getFileOffset() const;
 
1035         virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(log2(sizeof(typename A::P::uint_t))); }
 
1036         virtual uint32_t                                                getOrdinal() const              { return fOrdinal; }
 
1039         static uint32_t                                                 fgCurrentOrdinal;
 
1041         typedef typename A::P                                   P;
 
1044 template <typename A> uint32_t LinkEditAtom<A>::fgCurrentOrdinal = 0;
 
1046 template <typename A>
 
1047 class SectionRelocationsLinkEditAtom : public LinkEditAtom<A>
 
1050                                                                                         SectionRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
 
1051         virtual const char*                                             getDisplayName() const  { return "section relocations"; }
 
1052         virtual uint64_t                                                getSize() const;
 
1053         virtual const char*                                             getSectionName() const  { return "._section_relocs"; }
 
1054         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1056         using WriterAtom<A>::fWriter;
 
1057         typedef typename A::P                                   P;
 
1060 template <typename A>
 
1061 class CompressedInfoLinkEditAtom : public LinkEditAtom<A>
 
1064                                                                                         CompressedInfoLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
 
1065         virtual uint64_t                                                getSize() const { return fEncodedData.size(); }
 
1066         virtual void                                                    copyRawContent(uint8_t buffer[]) const { memcpy(buffer, fEncodedData.start(), fEncodedData.size()); }
 
1068         typedef typename A::P::uint_t                   pint_t;
 
1069         ByteStream                                                              fEncodedData;
 
1071         using WriterAtom<A>::fWriter;
 
1072         typedef typename A::P                                   P;
 
1077 template <typename A>
 
1078 class CompressedRebaseInfoLinkEditAtom : public CompressedInfoLinkEditAtom<A>
 
1081                                                                                         CompressedRebaseInfoLinkEditAtom(Writer<A>& writer) : CompressedInfoLinkEditAtom<A>(writer) { }
 
1082         virtual const char*                                             getDisplayName() const  { return "compressed rebase info"; }
 
1083         virtual const char*                                             getSectionName() const  { return "._rebase info"; }
 
1086         using CompressedInfoLinkEditAtom<A>::fEncodedData;
 
1087         using CompressedInfoLinkEditAtom<A>::fWriter;
 
1088         typedef typename A::P                                   P;
 
1089         typedef typename A::P::uint_t                   pint_t;
 
1092 template <typename A>
 
1093 class CompressedBindingInfoLinkEditAtom : public CompressedInfoLinkEditAtom<A>
 
1096                                                                                         CompressedBindingInfoLinkEditAtom(Writer<A>& writer) : CompressedInfoLinkEditAtom<A>(writer) { }
 
1097         virtual const char*                                             getDisplayName() const  { return "compressed binding info"; }
 
1098         virtual const char*                                             getSectionName() const  { return "._binding info"; }
 
1101         using CompressedInfoLinkEditAtom<A>::fWriter;
 
1102         using CompressedInfoLinkEditAtom<A>::fEncodedData;
 
1103         typedef typename A::P                                   P;
 
1104         typedef typename A::P::uint_t                   pint_t;
 
1107 template <typename A>
 
1108 class CompressedWeakBindingInfoLinkEditAtom : public CompressedInfoLinkEditAtom<A>
 
1111                                                                                         CompressedWeakBindingInfoLinkEditAtom(Writer<A>& writer) : CompressedInfoLinkEditAtom<A>(writer) { }
 
1112         virtual const char*                                             getDisplayName() const  { return "compressed weak binding info"; }
 
1113         virtual const char*                                             getSectionName() const  { return "._wkbinding info"; }
 
1116         using CompressedInfoLinkEditAtom<A>::fWriter;
 
1117         using CompressedInfoLinkEditAtom<A>::fEncodedData;
 
1118         typedef typename A::P                                   P;
 
1119         typedef typename A::P::uint_t                   pint_t;
 
1122 template <typename A>
 
1123 class CompressedLazyBindingInfoLinkEditAtom : public CompressedInfoLinkEditAtom<A>
 
1126                                                                                         CompressedLazyBindingInfoLinkEditAtom(Writer<A>& writer) : CompressedInfoLinkEditAtom<A>(writer) { }
 
1127         virtual const char*                                             getDisplayName() const  { return "compressed lazy binding info"; }
 
1128         virtual const char*                                             getSectionName() const  { return "._lzbinding info"; }
 
1131         std::vector<uint32_t>                                   fStarts;
 
1133         using CompressedInfoLinkEditAtom<A>::fWriter;
 
1134         using CompressedInfoLinkEditAtom<A>::fEncodedData;
 
1135         typedef typename A::P                                   P;
 
1136         typedef typename A::P::uint_t                   pint_t;
 
1140 template <typename A>
 
1141 class CompressedExportInfoLinkEditAtom : public CompressedInfoLinkEditAtom<A>
 
1144                                                                                         CompressedExportInfoLinkEditAtom(Writer<A>& writer) 
 
1145                                                                                         : CompressedInfoLinkEditAtom<A>(writer), fStartNode(strdup("")) { }
 
1146         virtual const char*                                             getDisplayName() const  { return "compressed export info"; }
 
1147         virtual const char*                                             getSectionName() const  { return "._export info"; }
 
1150         using WriterAtom<A>::fWriter;
 
1151         using CompressedInfoLinkEditAtom<A>::fEncodedData;
 
1152         typedef typename A::P                                   P;
 
1153         typedef typename A::P::uint_t                   pint_t;
 
1158                                                 edge(const char* s, struct node* n) : fSubString(s), fChild(n) { }
 
1160                 const char*             fSubString;
 
1161                 struct node*    fChild;
 
1167                                                         node(const char* s) : fCummulativeString(s), fAddress(0), fFlags(0), fOrdered(false), 
 
1168                                                                                                 fHaveExportInfo(false), fTrieOffset(0) {}
 
1170                 const char*                     fCummulativeString;
 
1171                 std::vector<edge>       fChildren;
 
1175                 bool                            fHaveExportInfo;
 
1176                 uint32_t                        fTrieOffset;
 
1178                 void addSymbol(const char* fullStr, uint64_t address, uint32_t flags) {
 
1179                         const char* partialStr = &fullStr[strlen(fCummulativeString)];
 
1180                         for (typename std::vector<edge>::iterator it = fChildren.begin(); it != fChildren.end(); ++it) {
 
1182                                 int subStringLen = strlen(e.fSubString);
 
1183                                 if ( strncmp(e.fSubString, partialStr, subStringLen) == 0 ) {
 
1184                                         // already have matching edge, go down that path
 
1185                                         e.fChild->addSymbol(fullStr, address, flags);
 
1189                                         for (int i=subStringLen-1; i > 0; --i) {
 
1190                                                 if ( strncmp(e.fSubString, partialStr, i) == 0 ) {
 
1191                                                         // found a common substring, splice in new node
 
1192                                                         //  was A -> C,  now A -> B -> C
 
1193                                                         char* bNodeCummStr = strdup(e.fChild->fCummulativeString);
 
1194                                                         bNodeCummStr[strlen(bNodeCummStr)+i-subStringLen] = '\0';
 
1195                                                         //node* aNode = this;
 
1196                                                         node* bNode = new node(bNodeCummStr);
 
1197                                                         node* cNode = e.fChild;
 
1198                                                         char* abEdgeStr = strdup(e.fSubString);
 
1199                                                         abEdgeStr[i] = '\0';
 
1200                                                         char* bcEdgeStr = strdup(&e.fSubString[i]);
 
1202                                                         abEdge.fSubString = abEdgeStr;
 
1203                                                         abEdge.fChild = bNode;
 
1204                                                         edge bcEdge(bcEdgeStr, cNode);
 
1205                                                         bNode->fChildren.push_back(bcEdge);
 
1206                                                         bNode->addSymbol(fullStr, address, flags);
 
1212                         // no commonality with any existing child, make a new edge that is this whole string
 
1213                         node* newNode = new node(strdup(fullStr));
 
1214                         edge newEdge(strdup(partialStr), newNode);
 
1215                         fChildren.push_back(newEdge);
 
1216                         newNode->fAddress = address;
 
1217                         newNode->fFlags = flags;
 
1218                         newNode->fHaveExportInfo = true;
 
1221                 void addOrderedNodes(const char* name, std::vector<node*>& orderedNodes) {
 
1223                                 orderedNodes.push_back(this);
 
1224                                 //fprintf(stderr, "ordered %p %s\n", this, fCummulativeString);
 
1227                         const char* partialStr = &name[strlen(fCummulativeString)];
 
1228                         for (typename std::vector<edge>::iterator it = fChildren.begin(); it != fChildren.end(); ++it) {
 
1230                                 int subStringLen = strlen(e.fSubString);
 
1231                                 if ( strncmp(e.fSubString, partialStr, subStringLen) == 0 ) {
 
1232                                         // already have matching edge, go down that path
 
1233                                         e.fChild->addOrderedNodes(name, orderedNodes);
 
1239                 // byte for terminal node size in bytes, or 0x00 if not terminal node
 
1240                 // teminal node (uleb128 flags, uleb128 addr)
 
1241                 // byte for child node count
 
1242                 //  each child: zero terminated substring, uleb128 node offset
 
1243                 bool updateOffset(uint32_t& offset) {
 
1244                         uint32_t nodeSize = 1; // byte for length of export info
 
1245                         if ( fHaveExportInfo ) 
 
1246                                 nodeSize += ByteStream::uleb128_size(fFlags) + ByteStream::uleb128_size(fAddress);
 
1249                         ++nodeSize; // byte for count of chidren
 
1250                         for (typename std::vector<edge>::iterator it = fChildren.begin(); it != fChildren.end(); ++it) {
 
1252                                 nodeSize += strlen(e.fSubString) + 1 + ByteStream::uleb128_size(e.fChild->fTrieOffset);
 
1254                         bool result = (fTrieOffset != offset);
 
1255                         fTrieOffset = offset;
 
1256                         //fprintf(stderr, "updateOffset %p %05d %s\n", this, fTrieOffset, fCummulativeString);
 
1258                         // return true if fTrieOffset was changed
 
1262                 void appendToStream(ByteStream& out) {
 
1263                         if ( fHaveExportInfo ) {
 
1264                                 // nodes with export info: size, flags, address
 
1265                                 out.append_byte(out.uleb128_size(fFlags) + out.uleb128_size(fAddress));
 
1266                                 out.append_uleb128(fFlags);
 
1267                                 out.append_uleb128(fAddress);
 
1273                         // write number of children
 
1274                         out.append_byte(fChildren.size());
 
1276                         for (typename std::vector<edge>::iterator it = fChildren.begin(); it != fChildren.end(); ++it) {
 
1278                                 out.append_string(e.fSubString);
 
1279                                 out.append_uleb128(e.fChild->fTrieOffset);
 
1286         struct node             fStartNode;
 
1289 template <typename A>
 
1290 class LocalRelocationsLinkEditAtom : public LinkEditAtom<A>
 
1293                                                                                         LocalRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
 
1294         virtual const char*                                             getDisplayName() const  { return "local relocations"; }
 
1295         virtual uint64_t                                                getSize() const;
 
1296         virtual const char*                                             getSectionName() const  { return "._local_relocs"; }
 
1297         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1299         using WriterAtom<A>::fWriter;
 
1300         typedef typename A::P                                   P;
 
1303 template <typename A>
 
1304 class SymbolTableLinkEditAtom : public LinkEditAtom<A>
 
1307                                                                                         SymbolTableLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
 
1308         virtual const char*                                             getDisplayName() const  { return "symbol table"; }
 
1309         virtual uint64_t                                                getSize() const;
 
1310         virtual const char*                                             getSectionName() const  { return "._symbol_table"; }
 
1311         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1313         using WriterAtom<A>::fWriter;
 
1314         typedef typename A::P                                   P;
 
1317 template <typename A>
 
1318 class ExternalRelocationsLinkEditAtom : public LinkEditAtom<A>
 
1321                                                                                         ExternalRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
 
1322         virtual const char*                                             getDisplayName() const  { return "external relocations"; }
 
1323         virtual uint64_t                                                getSize() const;
 
1324         virtual const char*                                             getSectionName() const  { return "._extern_relocs"; }
 
1325         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1327         using WriterAtom<A>::fWriter;
 
1328         typedef typename A::P                                   P;
 
1331 struct IndirectEntry {
 
1332         uint32_t        indirectIndex;
 
1333         uint32_t        symbolIndex;
 
1337 template <typename A>
 
1338 class SegmentSplitInfoContentAtom : public LinkEditAtom<A>
 
1341                                                                                         SegmentSplitInfoContentAtom(Writer<A>& writer) : LinkEditAtom<A>(writer), fCantEncode(false) { }
 
1342         virtual const char*                                             getDisplayName() const  { return "split segment info"; }
 
1343         virtual uint64_t                                                getSize() const;
 
1344         virtual const char*                                             getSectionName() const  { return "._split_info"; }
 
1345         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1346         bool                                                                    canEncode()                                             { return !fCantEncode; }
 
1347         void                                                                    setCantEncode()                                 { fCantEncode = true; }
 
1348         void                                                                    add32bitPointerLocation(const ObjectFile::Atom* atom, uint32_t offset) { fKind1Locations.push_back(AtomAndOffset(atom, offset)); }
 
1349         void                                                                    add64bitPointerLocation(const ObjectFile::Atom* atom, uint32_t offset) { fKind2Locations.push_back(AtomAndOffset(atom, offset)); }
 
1350         void                                                                    addPPCHi16Location(const ObjectFile::Atom* atom, uint32_t offset) { fKind3Locations.push_back(AtomAndOffset(atom, offset)); }
 
1351         void                                                                    add32bitImportLocation(const ObjectFile::Atom* atom, uint32_t offset) { fKind4Locations.push_back(AtomAndOffset(atom, offset)); }
 
1355         using WriterAtom<A>::fWriter;
 
1356         typedef typename A::P                                   P;
 
1357         typedef typename A::P::uint_t                   pint_t;
 
1358         struct AtomAndOffset { 
 
1359                         AtomAndOffset(const ObjectFile::Atom* a, uint32_t off) : atom(a), offset(off) {}
 
1360                         const ObjectFile::Atom*         atom; 
 
1363         void                                                                    uleb128EncodeAddresses(const std::vector<AtomAndOffset>& locations);
 
1365         std::vector<AtomAndOffset>                              fKind1Locations;
 
1366         std::vector<AtomAndOffset>                              fKind2Locations;
 
1367         std::vector<AtomAndOffset>                              fKind3Locations;
 
1368         std::vector<AtomAndOffset>                              fKind4Locations;
 
1369         std::vector<uint8_t>                                    fEncodedData;
 
1373 template <typename A>
 
1374 class IndirectTableLinkEditAtom : public LinkEditAtom<A>
 
1377                                                                                         IndirectTableLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
 
1378         virtual const char*                                             getDisplayName() const  { return "indirect symbol table"; }
 
1379         virtual uint64_t                                                getSize() const;
 
1380         virtual const char*                                             getSectionName() const  { return "._indirect_syms"; }
 
1381         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1383         std::vector<IndirectEntry>                              fTable;
 
1386         using WriterAtom<A>::fWriter;
 
1387         typedef typename A::P                                   P;
 
1390 template <typename A>
 
1391 class ModuleInfoLinkEditAtom : public LinkEditAtom<A>
 
1394                                                                                         ModuleInfoLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer), fModuleNameOffset(0) { }
 
1395         virtual const char*                                             getDisplayName() const  { return "module table"; }
 
1396         virtual uint64_t                                                getSize() const;
 
1397         virtual const char*                                             getSectionName() const  { return "._module_info"; }
 
1398         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1400                         void                                                    setName() { fModuleNameOffset = fWriter.fStringsAtom->add("single module"); }
 
1401                         uint32_t                                                getTableOfContentsFileOffset() const;
 
1402                         uint32_t                                                getModuleTableFileOffset() const;
 
1403                         uint32_t                                                getReferencesFileOffset() const;
 
1404                         uint32_t                                                getReferencesCount() const;
 
1407         using WriterAtom<A>::fWriter;
 
1408         typedef typename A::P                                   P;
 
1409         typedef typename A::P::uint_t                   pint_t;
 
1410         uint32_t                                                                fModuleNameOffset;
 
1417         bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
 
1420 template <typename A>
 
1421 class StringsLinkEditAtom : public LinkEditAtom<A>
 
1424                                                                                         StringsLinkEditAtom(Writer<A>& writer);
 
1425         virtual const char*                                             getDisplayName() const  { return "string pool"; }
 
1426         virtual uint64_t                                                getSize() const;
 
1427         virtual const char*                                             getSectionName() const  { return "._string_pool"; }
 
1428         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1430         int32_t                                                                 add(const char* name);
 
1431         int32_t                                                                 addUnique(const char* name);
 
1432         int32_t                                                                 emptyString()                   { return 1; }
 
1433         const char*                                                             stringForIndex(int32_t) const;
 
1436         using WriterAtom<A>::fWriter;
 
1437         typedef typename A::P                                   P;
 
1438         enum { kBufferSize = 0x01000000 };
 
1439         typedef __gnu_cxx::hash_map<const char*, int32_t, __gnu_cxx::hash<const char*>, CStringEquals> StringToOffset;
 
1441         std::vector<char*>                                              fFullBuffers;
 
1442         char*                                                                   fCurrentBuffer;
 
1443         uint32_t                                                                fCurrentBufferUsed;
 
1444         StringToOffset                                                  fUniqueStrings;
 
1449 template <typename A>
 
1450 class UndefinedSymbolProxyAtom : public WriterAtom<A>
 
1453                                                                                                         UndefinedSymbolProxyAtom(Writer<A>& writer, const char* name) : WriterAtom<A>(writer, Segment::fgLinkEditSegment), fName(name) {}
 
1454         virtual const char*                                                             getName() const                         { return fName; }
 
1455         virtual ObjectFile::Atom::Scope                                 getScope() const                        { return ObjectFile::Atom::scopeGlobal; }
 
1456         virtual ObjectFile::Atom::DefinitionKind                getDefinitionKind() const       { return ObjectFile::Atom::kExternalDefinition; }
 
1457         virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableIn; }
 
1458         virtual uint64_t                                                                getSize() const                         { return 0; }
 
1459         virtual const char*                                                             getSectionName() const          { return "._imports"; }
 
1461         using WriterAtom<A>::fWriter;
 
1462         typedef typename A::P                                   P;
 
1466 template <typename A>
 
1467 class BranchIslandAtom : public WriterAtom<A>
 
1470                                                                                         BranchIslandAtom(Writer<A>& writer, const char* name, int islandRegion, ObjectFile::Atom& target, 
 
1471                                                                                                                                                 ObjectFile::Atom& finalTarget, uint32_t finalTargetOffset);
 
1472         virtual const char*                                             getName() const                         { return fName; }
 
1473         virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
 
1474         virtual uint64_t                                                getSize() const;
 
1475         virtual bool                                                    isThumb() const                         { return (fIslandKind == kBranchIslandToThumb2); }
 
1476         virtual ObjectFile::Atom::ContentType   getContentType() const          { return ObjectFile::Atom::kBranchIsland; }
 
1477         virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableIn; }
 
1478         virtual const char*                                             getSectionName() const          { return "__text"; }
 
1479         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1480         uint64_t                                                                getFinalTargetAdress() const { return fFinalTarget.getAddress() + fFinalTargetOffset; }
 
1482         using WriterAtom<A>::fWriter;
 
1483         enum IslandKind { kBranchIslandToARM, kBranchIslandToThumb2, kBranchIslandToThumb1 };
 
1485         ObjectFile::Atom&                                               fTarget;
 
1486         ObjectFile::Atom&                                               fFinalTarget;
 
1487         uint32_t                                                                fFinalTargetOffset;
 
1488         IslandKind                                                              fIslandKind;
 
1491 template <typename A>
 
1492 class StubAtom : public WriterAtom<A>
 
1495                                                                                         StubAtom(Writer<A>& writer, ObjectFile::Atom& target, bool forLazyDylib);
 
1496         virtual const char*                                             getName() const                         { return fName; }
 
1497         virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
 
1498         virtual ObjectFile::Atom::ContentType   getContentType() const          { return ObjectFile::Atom::kStub; }
 
1499         virtual uint64_t                                                getSize() const;
 
1500         virtual ObjectFile::Alignment                   getAlignment() const;
 
1501         virtual const char*                                             getSectionName() const          { return "__symbol_stub1"; }
 
1502         virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
 
1503         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1504         ObjectFile::Atom*                                               getTarget()                                     { return &fTarget; }
 
1505         virtual uint32_t                                                getOrdinal() const                      { return fSortingOrdinal; }
 
1506         void                                                                    setSortingOrdinal(uint32_t o) { fSortingOrdinal = o; }
 
1508         static const char*                                              stubName(const char* importName);
 
1509         friend class LazyPointerAtom<A>;
 
1510         using WriterAtom<A>::fWriter;
 
1511         enum StubKind { kStubPIC, kStubNoPIC, kStubShort, kJumpTable };
 
1513         ObjectFile::Atom&                                               fTarget;
 
1514         std::vector<ObjectFile::Reference*>             fReferences;
 
1517         uint32_t                                                                fSortingOrdinal;
 
1521 template <typename A>
 
1522 class FastStubHelperHelperAtom : public WriterAtom<A>
 
1525                                                                                                         FastStubHelperHelperAtom(Writer<A>& writer);
 
1526         virtual const char*                                                             getName() const                                 { return " stub helpers"; }  // name sorts to start of helpers
 
1527         virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableIn; }
 
1528         virtual ObjectFile::Atom::Scope                                 getScope() const                                { return ObjectFile::Atom::scopeLinkageUnit; }
 
1529         virtual ObjectFile::Atom::ContentType                   getContentType() const                  { return ObjectFile::Atom::kStubHelper; }
 
1530         virtual uint64_t                                                                getSize() const;
 
1531         virtual const char*                                                             getSectionName() const                  { return "__stub_helper"; }
 
1532         virtual std::vector<ObjectFile::Reference*>&    getReferences() const                   { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
 
1533         virtual void                                                                    copyRawContent(uint8_t buffer[]) const;
 
1534         virtual ObjectFile::Alignment                                   getAlignment() const                    { return ObjectFile::Alignment(0); }
 
1535         virtual uint32_t                                                                getOrdinal() const                              { return 0; }
 
1537         using WriterAtom<A>::fWriter;
 
1538         std::vector<ObjectFile::Reference*>             fReferences;
 
1541 template <typename A>
 
1542 class HybridStubHelperHelperAtom : public WriterAtom<A>
 
1545                                                                                                         HybridStubHelperHelperAtom(Writer<A>& writer);
 
1546         virtual const char*                                                             getName() const                                 { return " stub helpers"; }  // name sorts to start of helpers
 
1547         virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableIn; }
 
1548         virtual ObjectFile::Atom::Scope                                 getScope() const                                { return ObjectFile::Atom::scopeLinkageUnit; }
 
1549         virtual ObjectFile::Atom::ContentType                   getContentType() const                  { return ObjectFile::Atom::kStubHelper; }
 
1550         virtual uint64_t                                                                getSize() const;
 
1551         virtual const char*                                                             getSectionName() const                  { return "__stub_helper"; }
 
1552         virtual std::vector<ObjectFile::Reference*>&    getReferences() const                   { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
 
1553         virtual void                                                                    copyRawContent(uint8_t buffer[]) const;
 
1554         virtual ObjectFile::Alignment                                   getAlignment() const                    { return ObjectFile::Alignment(0); }
 
1555         virtual uint32_t                                                                getOrdinal() const                              { return 0; }
 
1557         using WriterAtom<A>::fWriter;
 
1558         std::vector<ObjectFile::Reference*>             fReferences;
 
1561 template <typename A>
 
1562 class StubHelperAtom : public WriterAtom<A>
 
1565                                                                                         StubHelperAtom(Writer<A>& writer, ObjectFile::Atom& target, 
 
1566                                                                                                                 LazyPointerAtom<A>& lazyPointer, bool forLazyDylib) 
 
1567                                                                                                         : WriterAtom<A>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), 
 
1568                                                                                                                 fTarget(target), fLazyPointerAtom(lazyPointer) {
 
1569                                                                                                                         writer.fAllSynthesizedStubHelpers.push_back(this);
 
1572         virtual const char*                                             getName() const                         { return fName; }
 
1573         virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
 
1574         virtual ObjectFile::Atom::ContentType   getContentType() const          { return ObjectFile::Atom::kStubHelper; }
 
1575         virtual const char*                                             getSectionName() const          { return "__stub_helper"; }
 
1576         virtual std::vector<ObjectFile::Reference*>&  getReferences() const     { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
 
1577         ObjectFile::Atom*                                               getTarget()                                     { return &fTarget; }
 
1578         virtual ObjectFile::Alignment                   getAlignment() const            { return ObjectFile::Alignment(0); }
 
1579         virtual uint32_t                                                getOrdinal() const                      { return 1; }
 
1581         static const char*                                              stubName(const char* importName);
 
1582         using WriterAtom<A>::fWriter;
 
1584         ObjectFile::Atom&                                               fTarget;
 
1585         LazyPointerAtom<A>&                                             fLazyPointerAtom;
 
1586         std::vector<ObjectFile::Reference*>             fReferences;
 
1589 template <typename A>
 
1590 class ClassicStubHelperAtom : public StubHelperAtom<A>
 
1593                                                                                         ClassicStubHelperAtom(Writer<A>& writer, ObjectFile::Atom& target, 
 
1594                                                                                                                         class LazyPointerAtom<A>& lazyPointer, bool forLazyDylib);
 
1596         virtual uint64_t                                                getSize() const;
 
1597         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1601 template <typename A>
 
1602 class HybridStubHelperAtom : public StubHelperAtom<A>
 
1605                                                                                         HybridStubHelperAtom(Writer<A>& writer, ObjectFile::Atom& target, 
 
1606                                                                                                                         class LazyPointerAtom<A>& lazyPointer, bool forLazyDylib);
 
1608         virtual uint64_t                                                getSize() const;
 
1609         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1610         static class HybridStubHelperHelperAtom<A>*     fgHelperHelperAtom;
 
1612 template <typename A> class HybridStubHelperHelperAtom<A>* HybridStubHelperAtom<A>::fgHelperHelperAtom = NULL;
 
1614 template <typename A>
 
1615 class FastStubHelperAtom : public StubHelperAtom<A>
 
1618                                                                                         FastStubHelperAtom(Writer<A>& writer, ObjectFile::Atom& target, 
 
1619                                                                                                                                 class LazyPointerAtom<A>& lazyPointer, bool forLazyDylib);
 
1620         virtual uint64_t                                                getSize() const;
 
1621         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1622         static FastStubHelperHelperAtom<A>*             fgHelperHelperAtom;
 
1624 template <typename A>  FastStubHelperHelperAtom<A>* FastStubHelperAtom<A>::fgHelperHelperAtom = NULL;
 
1628 template <typename A>
 
1629 class LazyPointerAtom : public WriterAtom<A>
 
1632                                                                                         LazyPointerAtom(Writer<A>& writer, ObjectFile::Atom& target, 
 
1633                                                                                                                         StubAtom<A>& stub, bool forLazyDylib);
 
1634         virtual const char*                                             getName() const                         { return fName; }
 
1635         virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeTranslationUnit; }
 
1636         virtual ObjectFile::Atom::ContentType   getContentType() const          { return fForLazyDylib ? ObjectFile::Atom::kLazyDylibPointer : ObjectFile::Atom::kLazyPointer; }
 
1637         virtual uint64_t                                                getSize() const                         { return sizeof(typename A::P::uint_t); }
 
1638         virtual const char*                                             getSectionName() const;
 
1639         virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
 
1640         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1641         ObjectFile::Atom*                                               getTarget()                                     { return &fExternalTarget; }
 
1642         void                                                                    setLazyBindingInfoOffset(uint32_t off) { fLazyBindingOffset = off; }
 
1643         uint32_t                                                                getLazyBindingInfoOffset()      { return fLazyBindingOffset; }
 
1644         virtual uint32_t                                                getOrdinal() const                      { return fSortingOrdinal; }
 
1645         void                                                                    setSortingOrdinal(uint32_t o) { fSortingOrdinal = o; }
 
1647         using WriterAtom<A>::fWriter;
 
1648         static const char*                                              lazyPointerName(const char* importName);
 
1650         ObjectFile::Atom&                                               fTarget;
 
1651         ObjectFile::Atom&                                               fExternalTarget;
 
1652         std::vector<ObjectFile::Reference*>             fReferences;
 
1655         uint32_t                                                                fLazyBindingOffset;
 
1656         uint32_t                                                                fSortingOrdinal;
 
1660 template <typename A>
 
1661 class NonLazyPointerAtom : public WriterAtom<A>
 
1664                                                                                         NonLazyPointerAtom(Writer<A>& writer, ObjectFile::Atom& target);
 
1665                                                                                         NonLazyPointerAtom(Writer<A>& writer, const char* targetName);
 
1666                                                                                         NonLazyPointerAtom(Writer<A>& writer);
 
1667         virtual const char*                                             getName() const                         { return fName; }
 
1668         virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
 
1669         virtual ObjectFile::Atom::ContentType   getContentType() const          { return ObjectFile::Atom::kNonLazyPointer; }
 
1670         virtual uint64_t                                                getSize() const                         { return sizeof(typename A::P::uint_t); }
 
1671         virtual const char*                                             getSectionName() const          { return (fWriter.fOptions.outputKind() == Options::kKextBundle) ? "__got" : "__nl_symbol_ptr"; }
 
1672         virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
 
1673         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1674         ObjectFile::Atom*                                               getTarget()                                     { return fTarget; }
 
1675         virtual uint32_t                                                getOrdinal() const                      { return fSortingOrdinal; }
 
1676         void                                                                    setSortingOrdinal(uint32_t o) { fSortingOrdinal = o; }
 
1678         using WriterAtom<A>::fWriter;
 
1679         static const char*                                              nonlazyPointerName(const char* importName);
 
1681         ObjectFile::Atom*                                               fTarget;
 
1682         std::vector<ObjectFile::Reference*>             fReferences;
 
1683         uint32_t                                                                fSortingOrdinal;
 
1687 template <typename A>
 
1688 class ObjCInfoAtom : public WriterAtom<A>
 
1691                                                                                         ObjCInfoAtom(Writer<A>& writer, ObjectFile::Reader::ObjcConstraint objcContraint,
 
1692                                                                                                                 bool objcReplacementClasses);
 
1693         virtual const char*                                             getName() const                         { return "objc$info"; }
 
1694         virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
 
1695         virtual uint64_t                                                getSize() const                         { return 8; }
 
1696         virtual const char*                                             getSectionName() const;
 
1697         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1699         Segment&                                                                getInfoSegment() const;
 
1700         uint32_t                                                                fContent[2];
 
1704 template <typename A>
 
1705 class WriterReference : public ObjectFile::Reference
 
1708         typedef typename A::ReferenceKinds                      Kinds;
 
1710                                                         WriterReference(uint32_t offset, Kinds kind, ObjectFile::Atom* target,
 
1711                                                                                         uint32_t toOffset=0, ObjectFile::Atom* fromTarget=NULL, uint32_t fromOffset=0)
 
1712                                                                                   : fKind(kind), fFixUpOffsetInSrc(offset), fTarget(target), fTargetName(target->getName()),
 
1713                                                                                         fTargetOffset(toOffset), fFromTarget(fromTarget), fFromTargetOffset(fromOffset) {}
 
1714                                                         WriterReference(uint32_t offset, Kinds kind, const char* targetName)
 
1715                                                                                   : fKind(kind), fFixUpOffsetInSrc(offset), fTarget(NULL), fTargetName(targetName),
 
1716                                                                                         fTargetOffset(0), fFromTarget(NULL), fFromTargetOffset(0) {}
 
1718         virtual                                 ~WriterReference() {}
 
1720         virtual ObjectFile::Reference::TargetBinding getTargetBinding() const { return (fTarget != NULL) ? ObjectFile::Reference::kBoundDirectly :  ObjectFile::Reference::kUnboundByName; }
 
1721         virtual ObjectFile::Reference::TargetBinding getFromTargetBinding() const { return (fFromTarget != NULL) ? ObjectFile::Reference::kBoundDirectly : ObjectFile::Reference::kDontBind; }
 
1722         virtual uint8_t                 getKind() const                                                                 { return (uint8_t)fKind; }
 
1723         virtual uint64_t                getFixUpOffset() const                                                  { return fFixUpOffsetInSrc; }
 
1724         virtual const char*             getTargetName() const                                                   { return fTargetName; }
 
1725         virtual ObjectFile::Atom& getTarget() const                                                             { return *fTarget; }
 
1726         virtual uint64_t                getTargetOffset() const                                                 { return fTargetOffset; }
 
1727         virtual ObjectFile::Atom& getFromTarget() const                                                 { return *fFromTarget; }
 
1728         virtual const char*             getFromTargetName() const                                               { return fFromTarget->getName(); }
 
1729         virtual void                    setTarget(ObjectFile::Atom& target, uint64_t offset)    { fTarget = ⌖ fTargetOffset = offset; }
 
1730         virtual void                    setFromTarget(ObjectFile::Atom& target)                 { fFromTarget = ⌖ }
 
1731         virtual void                    setFromTargetName(const char* name)                             {  }
 
1732         virtual void                    setFromTargetOffset(uint64_t offset)                    { fFromTargetOffset = offset; }
 
1733         virtual const char*             getDescription() const                                                  { return "writer reference"; }
 
1734         virtual uint64_t                getFromTargetOffset() const                                             { return fFromTargetOffset; }
 
1738         uint32_t                                fFixUpOffsetInSrc;
 
1739         ObjectFile::Atom*               fTarget;
 
1740         const char*                             fTargetName;
 
1741         uint32_t                                fTargetOffset;
 
1742         ObjectFile::Atom*               fFromTarget;
 
1743         uint32_t                                fFromTargetOffset;
 
1747 template <typename A>
 
1748 const char* StubHelperAtom<A>::stubName(const char* name)
 
1751         asprintf(&buf, "%s$stubHelper", name);
 
1756 ClassicStubHelperAtom<x86_64>::ClassicStubHelperAtom(Writer<x86_64>& writer, ObjectFile::Atom& target, 
 
1757                                                                                                                         class LazyPointerAtom<x86_64>& lazyPointer, bool forLazyDylib)
 
1758         : StubHelperAtom<x86_64>(writer, target, lazyPointer, forLazyDylib)
 
1760         fReferences.push_back(new WriterReference<x86_64>(3, x86_64::kPCRel32, &fLazyPointerAtom));
 
1761         if ( forLazyDylib ) {
 
1762                 if ( fWriter.fDyldLazyDylibHelper == NULL )
 
1763                         throw "symbol dyld_lazy_dylib_stub_binding_helper not defined (usually in lazydylib1.o)";
 
1764                 fReferences.push_back(new WriterReference<x86_64>(8, x86_64::kPCRel32, fWriter.fDyldLazyDylibHelper));
 
1767                 if ( fWriter.fDyldClassicHelperAtom == NULL )
 
1768                         throw "symbol dyld_stub_binding_helper not defined (usually in crt1.o/dylib1.o/bundle1.o)";
 
1769                 fReferences.push_back(new WriterReference<x86_64>(8, x86_64::kPCRel32, fWriter.fDyldClassicHelperAtom));
 
1775 uint64_t ClassicStubHelperAtom<x86_64>::getSize() const
 
1781 void ClassicStubHelperAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
 
1783         buffer[0]  = 0x4C;              // lea foo$lazy_ptr(%rip),%r11
 
1790         buffer[7]  = 0xE9;              // jmp dyld_stub_binding_helper
 
1799 FastStubHelperHelperAtom<x86_64>::FastStubHelperHelperAtom(Writer<x86_64>& writer)
 
1800         : WriterAtom<x86_64>(writer, Segment::fgTextSegment)
 
1802         fReferences.push_back(new WriterReference<x86_64>(3, x86_64::kPCRel32, new NonLazyPointerAtom<x86_64>(writer)));
 
1803         fReferences.push_back(new WriterReference<x86_64>(11, x86_64::kPCRel32, writer.fFastStubGOTAtom));
 
1807 uint64_t FastStubHelperHelperAtom<x86_64>::getSize() const
 
1813 void FastStubHelperHelperAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
 
1815         buffer[0]  = 0x4C;              // leaq dyld_mageLoaderCache(%rip),%r11
 
1822         buffer[7]  = 0x41;              // pushq %r11
 
1824         buffer[9]  = 0xFF;              // jmp *_fast_lazy_bind(%rip)
 
1830         buffer[15] = 0x90;              // nop
 
1835 HybridStubHelperHelperAtom<x86_64>::HybridStubHelperHelperAtom(Writer<x86_64>& writer)
 
1836         : WriterAtom<x86_64>(writer, Segment::fgTextSegment)
 
1838         if ( writer.fDyldClassicHelperAtom == NULL )
 
1839                 throw "symbol dyld_stub_binding_helper not defined (usually in crt1.o/dylib1.o/bundle1.o)";
 
1840         fReferences.push_back(new WriterReference<x86_64>(3, x86_64::kPCRel32_1, writer.fFastStubGOTAtom));
 
1841         fReferences.push_back(new WriterReference<x86_64>(13, x86_64::kPCRel32, new NonLazyPointerAtom<x86_64>(writer)));
 
1842         fReferences.push_back(new WriterReference<x86_64>(21, x86_64::kPCRel32, writer.fFastStubGOTAtom));
 
1843         fReferences.push_back(new WriterReference<x86_64>(30, x86_64::kPCRel32, writer.fDyldClassicHelperAtom));
 
1847 uint64_t HybridStubHelperHelperAtom<x86_64>::getSize() const
 
1853 void HybridStubHelperHelperAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
 
1855         buffer[0]  = 0x48;              // cmpl $0x00,_fast_lazy_bind
 
1863         buffer[8]  = 0x74;              // je 16
 
1865         buffer[10] = 0x4C;              // leaq imageCache(%rip),%r11
 
1872         buffer[17] = 0x41;              // pushq %r11
 
1874         buffer[19] = 0xFF;              // jmp *_fast_lazy_bind(%rip)
 
1880         buffer[25] = 0x48;              // addq $8,%rsp
 
1884         buffer[29] = 0xE9;              // jmp dyld_stub_binding_helper
 
1893 HybridStubHelperAtom<x86_64>::HybridStubHelperAtom(Writer<x86_64>& writer, ObjectFile::Atom& target, 
 
1894                                                                                                                         class LazyPointerAtom<x86_64>& lazyPointer, bool forLazyDylib)
 
1895         : StubHelperAtom<x86_64>(writer, target, lazyPointer, forLazyDylib)
 
1897         if ( fgHelperHelperAtom == NULL ) {
 
1898                 fgHelperHelperAtom = new HybridStubHelperHelperAtom<x86_64>::HybridStubHelperHelperAtom(fWriter);
 
1899                 fWriter.fAllSynthesizedStubHelpers.push_back(fgHelperHelperAtom);
 
1901         fReferences.push_back(new WriterReference<x86_64>(8,  x86_64::kPCRel32, &fLazyPointerAtom));
 
1902         fReferences.push_back(new WriterReference<x86_64>(13, x86_64::kPCRel32, fgHelperHelperAtom));
 
1906 uint64_t HybridStubHelperAtom<x86_64>::getSize() const
 
1912 void HybridStubHelperAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
 
1914         buffer[0]  = 0x68;              // pushq $lazy-info-offset
 
1919         buffer[5]  = 0x4C;              // lea foo$lazy_ptr(%rip),%r11
 
1926         buffer[12] = 0xE9;              // jmp helper-helper
 
1931         buffer[17] = 0x90;              // nop
 
1933         // the lazy binding info is created later than this helper atom, so there
 
1934         // is no Reference to update.  Instead we blast the offset here.
 
1936         LittleEndian::set32(offset, fLazyPointerAtom.getLazyBindingInfoOffset());
 
1937         memcpy(&buffer[1], &offset, 4);
 
1941 FastStubHelperAtom<x86_64>::FastStubHelperAtom(Writer<x86_64>& writer, ObjectFile::Atom& target, 
 
1942                                                                                                                         class LazyPointerAtom<x86_64>& lazyPointer, bool forLazyDylib)
 
1943         : StubHelperAtom<x86_64>(writer, target, lazyPointer, forLazyDylib)
 
1945         if ( fgHelperHelperAtom == NULL ) {
 
1946                 fgHelperHelperAtom = new FastStubHelperHelperAtom<x86_64>::FastStubHelperHelperAtom(fWriter);
 
1947                 fWriter.fAllSynthesizedStubHelpers.push_back(fgHelperHelperAtom);
 
1949         fReferences.push_back(new WriterReference<x86_64>(6, x86_64::kPCRel32, fgHelperHelperAtom));
 
1953 uint64_t FastStubHelperAtom<x86_64>::getSize() const
 
1959 void FastStubHelperAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
 
1961         buffer[0]  = 0x68;              // pushq $lazy-info-offset
 
1966         buffer[5]  = 0xE9;              // jmp helperhelper
 
1972         // the lazy binding info is created later than this helper atom, so there
 
1973         // is no Reference to update.  Instead we blast the offset here.
 
1975         LittleEndian::set32(offset, fLazyPointerAtom.getLazyBindingInfoOffset());
 
1976         memcpy(&buffer[1], &offset, 4);
 
1980 FastStubHelperHelperAtom<x86>::FastStubHelperHelperAtom(Writer<x86>& writer)
 
1981         : WriterAtom<x86>(writer, Segment::fgTextSegment)
 
1983         fReferences.push_back(new WriterReference<x86>(1, x86::kAbsolute32, new NonLazyPointerAtom<x86>(writer)));
 
1984         fReferences.push_back(new WriterReference<x86>(7, x86::kAbsolute32, writer.fFastStubGOTAtom));
 
1988 uint64_t FastStubHelperHelperAtom<x86>::getSize() const
 
1994 void FastStubHelperHelperAtom<x86>::copyRawContent(uint8_t buffer[]) const
 
1996         buffer[0]  = 0x68;              // pushl $dyld_ImageLoaderCache
 
2001         buffer[5]  = 0xFF;              // jmp *_fast_lazy_bind
 
2007         buffer[11] = 0x90;              // nop
 
2012 FastStubHelperHelperAtom<arm>::FastStubHelperHelperAtom(Writer<arm>& writer)
 
2013         : WriterAtom<arm>(writer, Segment::fgTextSegment)
 
2015         fReferences.push_back(new WriterReference<arm>(28, arm::kPointerDiff, new NonLazyPointerAtom<arm>(writer), 0, this, 16));
 
2016         fReferences.push_back(new WriterReference<arm>(32, arm::kPointerDiff, writer.fFastStubGOTAtom, 0, this, 28));
 
2020 uint64_t FastStubHelperHelperAtom<arm>::getSize() const
 
2026 void FastStubHelperHelperAtom<arm>::copyRawContent(uint8_t buffer[]) const
 
2028         // push lazy-info-offset
 
2029         OSWriteLittleInt32(&buffer[ 0], 0, 0xe52dc004); // str ip, [sp, #-4]!
 
2030         // push address of dyld_mageLoaderCache
 
2031         OSWriteLittleInt32(&buffer[ 4], 0, 0xe59fc010); // ldr  ip, L1
 
2032         OSWriteLittleInt32(&buffer[ 8], 0, 0xe08fc00c); // add  ip, pc, ip
 
2033         OSWriteLittleInt32(&buffer[12], 0, 0xe52dc004); // str ip, [sp, #-4]!
 
2034         // jump through _fast_lazy_bind
 
2035         OSWriteLittleInt32(&buffer[16], 0, 0xe59fc008); // ldr  ip, L2
 
2036         OSWriteLittleInt32(&buffer[20], 0, 0xe08fc00c); // add  ip, pc, ip
 
2037         OSWriteLittleInt32(&buffer[24], 0, 0xe59cf000); // ldr  pc, [ip]
 
2038         OSWriteLittleInt32(&buffer[28], 0, 0x00000000); // L1: .long fFastStubGOTAtom - (helperhelper+16)
 
2039         OSWriteLittleInt32(&buffer[32], 0, 0x00000000); // L2: .long _fast_lazy_bind - (helperhelper+28)
 
2043 ObjectFile::Alignment StubHelperAtom<arm>::getAlignment() const         { return ObjectFile::Alignment(2); }
 
2046 FastStubHelperAtom<arm>::FastStubHelperAtom(Writer<arm>& writer, ObjectFile::Atom& target, 
 
2047                                                                                         class LazyPointerAtom<arm>& lazyPointer, bool forLazyDylib)
 
2048         : StubHelperAtom<arm>(writer, target, lazyPointer, forLazyDylib)
 
2050         if ( fgHelperHelperAtom == NULL ) {
 
2051                 fgHelperHelperAtom = new FastStubHelperHelperAtom<arm>::FastStubHelperHelperAtom(fWriter);
 
2052                 fWriter.fAllSynthesizedStubHelpers.push_back(fgHelperHelperAtom);
 
2054         fReferences.push_back(new WriterReference<arm>(4, arm::kBranch24, fgHelperHelperAtom));
 
2058 uint64_t FastStubHelperAtom<arm>::getSize() const
 
2064 void FastStubHelperAtom<arm>::copyRawContent(uint8_t buffer[]) const
 
2066         OSWriteLittleInt32(&buffer[0], 0, 0xe59fc000); // ldr  ip, [pc, #0]
 
2067         OSWriteLittleInt32(&buffer[4], 0, 0xea000000); // b     _helperhelper
 
2068         // the lazy binding info is created later than this helper atom, so there
 
2069         // is no Reference to update.  Instead we blast the offset here.
 
2070         OSWriteLittleInt32(&buffer[8], 0, fLazyPointerAtom.getLazyBindingInfoOffset());
 
2075 HybridStubHelperHelperAtom<x86>::HybridStubHelperHelperAtom(Writer<x86>& writer)
 
2076         : WriterAtom<x86>(writer, Segment::fgTextSegment)
 
2078         if ( writer.fDyldClassicHelperAtom == NULL )
 
2079                 throw "symbol dyld_stub_binding_helper not defined (usually in crt1.o/dylib1.o/bundle1.o)";
 
2080         fReferences.push_back(new WriterReference<x86>(2,  x86::kAbsolute32, writer.fFastStubGOTAtom));
 
2081         fReferences.push_back(new WriterReference<x86>(18, x86::kPCRel32, writer.fDyldClassicHelperAtom));
 
2082         fReferences.push_back(new WriterReference<x86>(26, x86::kAbsolute32, new NonLazyPointerAtom<x86>(writer)));
 
2083         fReferences.push_back(new WriterReference<x86>(32, x86::kAbsolute32, writer.fFastStubGOTAtom));
 
2087 uint64_t HybridStubHelperHelperAtom<x86>::getSize() const
 
2094 void HybridStubHelperHelperAtom<x86>::copyRawContent(uint8_t buffer[]) const
 
2096         buffer[0]  = 0x83;              // cmpl $0x00,_fast_lazy_bind
 
2103         buffer[7]  = 0x75;              // jne 22
 
2105         buffer[9]  = 0x89;              // %eax,4(%esp)
 
2109         buffer[13] = 0x58;              // popl  %eax
 
2110         buffer[14] = 0x87;              // xchgl (%esp),%eax
 
2113         buffer[17] = 0xE9;              // jmpl dyld_stub_binding_helper
 
2118         buffer[22] = 0x83;              // addl $0x04,%esp
 
2121         buffer[25] = 0x68;              // pushl imageloadercahce
 
2126         buffer[30] = 0xFF;              // jmp *_fast_lazy_bind(%rip)
 
2136 ClassicStubHelperAtom<x86>::ClassicStubHelperAtom(Writer<x86>& writer, ObjectFile::Atom& target, 
 
2137                                                                                                                         class LazyPointerAtom<x86>& lazyPointer, bool forLazyDylib)
 
2138         : StubHelperAtom<x86>(writer, target, lazyPointer, forLazyDylib)
 
2140         fReferences.push_back(new WriterReference<x86>(1, x86::kAbsolute32, &fLazyPointerAtom));
 
2141         if ( forLazyDylib ) {
 
2142                 if ( fWriter.fDyldLazyDylibHelper == NULL )
 
2143                         throw "symbol dyld_lazy_dylib_stub_binding_helper not defined (usually in lazydylib1.o)";
 
2144                 fReferences.push_back(new WriterReference<x86>(6, x86::kPCRel32, fWriter.fDyldLazyDylibHelper));
 
2147                 if ( fWriter.fDyldClassicHelperAtom == NULL )
 
2148                         throw "symbol dyld_stub_binding_helper not defined (usually in crt1.o/dylib1.o/bundle1.o)";
 
2149                 fReferences.push_back(new WriterReference<x86>(6, x86::kPCRel32, fWriter.fDyldClassicHelperAtom));
 
2154 uint64_t ClassicStubHelperAtom<x86>::getSize() const
 
2160 void ClassicStubHelperAtom<x86>::copyRawContent(uint8_t buffer[]) const
 
2162         buffer[0]  = 0x68;              // pushl $foo$lazy_ptr
 
2167         buffer[5]  = 0xE9;              // jmp helperhelper
 
2175 HybridStubHelperAtom<x86>::HybridStubHelperAtom(Writer<x86>& writer, ObjectFile::Atom& target, 
 
2176                                                                                                                         class LazyPointerAtom<x86>& lazyPointer, bool forLazyDylib)
 
2177         : StubHelperAtom<x86>(writer, target, lazyPointer, forLazyDylib)
 
2179         if ( fgHelperHelperAtom == NULL ) {
 
2180                 fgHelperHelperAtom = new HybridStubHelperHelperAtom<x86>::HybridStubHelperHelperAtom(fWriter);
 
2181                 fWriter.fAllSynthesizedStubHelpers.push_back(fgHelperHelperAtom);
 
2183         fReferences.push_back(new WriterReference<x86>(6,  x86::kAbsolute32, &fLazyPointerAtom));
 
2184         fReferences.push_back(new WriterReference<x86>(11, x86::kPCRel32, fgHelperHelperAtom));
 
2189 uint64_t HybridStubHelperAtom<x86>::getSize() const
 
2195 void HybridStubHelperAtom<x86>::copyRawContent(uint8_t buffer[]) const
 
2197         buffer[0]  = 0x68;              // pushl $lazy-info-offset
 
2202         buffer[5]  = 0x68;              // pushl $foo$lazy_ptr
 
2207         buffer[10] = 0xE9;              // jmp dyld_hybrid_stub_binding_helper
 
2212         buffer[15] = 0x90;              // nop
 
2214         // the lazy binding info is created later than this helper atom, so there
 
2215         // is no Reference to update.  Instead we blast the offset here.
 
2217         LittleEndian::set32(offset, fLazyPointerAtom.getLazyBindingInfoOffset());
 
2218         memcpy(&buffer[1], &offset, 4); 
 
2223 FastStubHelperAtom<x86>::FastStubHelperAtom(Writer<x86>& writer, ObjectFile::Atom& target, 
 
2224                                                                                                                         class LazyPointerAtom<x86>& lazyPointer, bool forLazyDylib)
 
2225         : StubHelperAtom<x86>(writer, target, lazyPointer, forLazyDylib)
 
2227         if ( fgHelperHelperAtom == NULL ) {
 
2228                 fgHelperHelperAtom = new FastStubHelperHelperAtom<x86>::FastStubHelperHelperAtom(fWriter);
 
2229                 fWriter.fAllSynthesizedStubHelpers.push_back(fgHelperHelperAtom);
 
2231         fReferences.push_back(new WriterReference<x86>(6, x86::kPCRel32, fgHelperHelperAtom));
 
2236 uint64_t FastStubHelperAtom<x86>::getSize() const
 
2242 void FastStubHelperAtom<x86>::copyRawContent(uint8_t buffer[]) const
 
2244         buffer[0]  = 0x68;              // pushl $lazy-info-offset
 
2249         buffer[5]  = 0xE9;              // jmp helperhelper
 
2255         // the lazy binding info is created later than this helper atom, so there
 
2256         // is no Reference to update.  Instead we blast the offset here.
 
2258         LittleEndian::set32(offset, fLazyPointerAtom.getLazyBindingInfoOffset());
 
2259         memcpy(&buffer[1], &offset, 4);
 
2262 template <typename A>
 
2263 const char* LazyPointerAtom<A>::getSectionName() const
 
2266                 return "__lazy_symbol";
 
2267         else if ( fForLazyDylib )
 
2268                 return "__ld_symbol_ptr";
 
2270                 return "__la_symbol_ptr"; 
 
2273 // specialize lazy pointer for x86_64 to initially pointer to stub helper
 
2275 LazyPointerAtom<x86_64>::LazyPointerAtom(Writer<x86_64>& writer, ObjectFile::Atom& target, StubAtom<x86_64>& stub, bool forLazyDylib)
 
2276  : WriterAtom<x86_64>(writer, Segment::fgDataSegment), fName(lazyPointerName(target.getName())), fTarget(target), 
 
2277         fExternalTarget(*stub.getTarget()), fForLazyDylib(forLazyDylib), fCloseStub(false), fLazyBindingOffset(0)
 
2280                 writer.fAllSynthesizedLazyDylibPointers.push_back(this);
 
2282                 writer.fAllSynthesizedLazyPointers.push_back(this);
 
2284         ObjectFile::Atom* helper;
 
2285         if ( writer.fOptions.makeCompressedDyldInfo() && !forLazyDylib ) {
 
2286                 if ( writer.fOptions.makeClassicDyldInfo() ) 
 
2287                         // hybrid LINKEDIT, no fast bind info for weak symbols so use traditional helper
 
2288                         if ( writer.targetRequiresWeakBinding(target) )
 
2289                                 helper = new ClassicStubHelperAtom<x86_64>(writer, target, *this, forLazyDylib);
 
2291                                 helper = new HybridStubHelperAtom<x86_64>(writer, target, *this, forLazyDylib);
 
2293                         if ( target.getDefinitionKind() == ObjectFile::Atom::kWeakDefinition ) 
 
2296                                 helper = new FastStubHelperAtom<x86_64>(writer, target, *this, forLazyDylib);
 
2300                 helper = new ClassicStubHelperAtom<x86_64>(writer, target, *this, forLazyDylib);
 
2302         fReferences.push_back(new WriterReference<x86_64>(0, x86_64::kPointer, helper));
 
2306 // specialize lazy pointer for x86 to initially pointer to stub helper
 
2308 LazyPointerAtom<x86>::LazyPointerAtom(Writer<x86>& writer, ObjectFile::Atom& target, StubAtom<x86>& stub, bool forLazyDylib)
 
2309  : WriterAtom<x86>(writer, Segment::fgDataSegment), fName(lazyPointerName(target.getName())), fTarget(target), 
 
2310         fExternalTarget(*stub.getTarget()), fForLazyDylib(forLazyDylib), fCloseStub(false), fLazyBindingOffset(0)
 
2313                 writer.fAllSynthesizedLazyDylibPointers.push_back(this);
 
2315                 writer.fAllSynthesizedLazyPointers.push_back(this);
 
2317         ObjectFile::Atom* helper;
 
2318         if ( writer.fOptions.makeCompressedDyldInfo() && !forLazyDylib ) {
 
2319                 if ( writer.fOptions.makeClassicDyldInfo() ) {
 
2320                         // hybrid LINKEDIT, no fast bind info for weak symbols so use traditional helper
 
2321                         if ( writer.targetRequiresWeakBinding(target) )
 
2322                                 helper = new ClassicStubHelperAtom<x86>(writer, target, *this, forLazyDylib);
 
2324                                 helper = new HybridStubHelperAtom<x86>(writer, target, *this, forLazyDylib);
 
2327                         if ( target.getDefinitionKind() == ObjectFile::Atom::kWeakDefinition ) 
 
2330                                 helper = new FastStubHelperAtom<x86>(writer, target, *this, forLazyDylib);
 
2334                 helper = new ClassicStubHelperAtom<x86>(writer, target, *this, forLazyDylib);
 
2336         fReferences.push_back(new WriterReference<x86>(0, x86::kPointer, helper));
 
2339 // specialize lazy pointer for arm to initially pointer to stub helper
 
2341 LazyPointerAtom<arm>::LazyPointerAtom(Writer<arm>& writer, ObjectFile::Atom& target, StubAtom<arm>& stub, bool forLazyDylib)
 
2342  : WriterAtom<arm>(writer, Segment::fgDataSegment), fName(lazyPointerName(target.getName())), fTarget(target), 
 
2343         fExternalTarget(*stub.getTarget()), fForLazyDylib(forLazyDylib), fCloseStub(false), fLazyBindingOffset(0)
 
2346                 writer.fAllSynthesizedLazyDylibPointers.push_back(this);
 
2348                 writer.fAllSynthesizedLazyPointers.push_back(this);
 
2350         // The one instruction stubs must be close to the lazy pointers
 
2351         if ( stub.fKind == StubAtom<arm>::kStubShort )
 
2354         ObjectFile::Atom* helper;
 
2355         if ( forLazyDylib ) {
 
2356                 if ( writer.fDyldLazyDylibHelper == NULL )
 
2357                         throw "symbol dyld_lazy_dylib_stub_binding_helper not defined (usually in lazydylib1.o)";
 
2358                 helper = writer.fDyldLazyDylibHelper;
 
2360         else if ( writer.fOptions.makeCompressedDyldInfo() ) {
 
2361                 if ( target.getDefinitionKind() == ObjectFile::Atom::kWeakDefinition ) 
 
2364                         helper = new FastStubHelperAtom<arm>(writer, target, *this, forLazyDylib);
 
2367                 if ( writer.fDyldClassicHelperAtom == NULL )
 
2368                         throw "symbol dyld_stub_binding_helper not defined (usually in crt1.o/dylib1.o/bundle1.o)";
 
2369                 helper = writer.fDyldClassicHelperAtom;
 
2371         fReferences.push_back(new WriterReference<arm>(0, arm::kPointer, helper));
 
2374 template <typename A>
 
2375 LazyPointerAtom<A>::LazyPointerAtom(Writer<A>& writer, ObjectFile::Atom& target, StubAtom<A>& stub, bool forLazyDylib)
 
2376  : WriterAtom<A>(writer, Segment::fgDataSegment), fName(lazyPointerName(target.getName())), fTarget(target), 
 
2377         fExternalTarget(*stub.getTarget()), fForLazyDylib(forLazyDylib), fCloseStub(false), fLazyBindingOffset(0)
 
2380                 writer.fAllSynthesizedLazyDylibPointers.push_back(this);
 
2382                 writer.fAllSynthesizedLazyPointers.push_back(this);
 
2384         fReferences.push_back(new WriterReference<A>(0, A::kPointer, &target));
 
2389 template <typename A>
 
2390 const char* LazyPointerAtom<A>::lazyPointerName(const char* name)
 
2393         asprintf(&buf, "%s$lazy_pointer", name);
 
2397 template <typename A>
 
2398 void LazyPointerAtom<A>::copyRawContent(uint8_t buffer[]) const
 
2400         bzero(buffer, getSize());
 
2404 template <typename A>
 
2405 NonLazyPointerAtom<A>::NonLazyPointerAtom(Writer<A>& writer, ObjectFile::Atom& target)
 
2406  : WriterAtom<A>(writer, Segment::fgDataSegment), fName(nonlazyPointerName(target.getName())), fTarget(&target)
 
2408         writer.fAllSynthesizedNonLazyPointers.push_back(this);
 
2409         fReferences.push_back(new WriterReference<A>(0, A::kPointer, &target));
 
2412 template <typename A>
 
2413 NonLazyPointerAtom<A>::NonLazyPointerAtom(Writer<A>& writer)
 
2414  : WriterAtom<A>(writer, Segment::fgDataSegment), fName("none"), fTarget(NULL)
 
2416         writer.fAllSynthesizedNonLazyPointers.push_back(this);
 
2419 template <typename A>
 
2420 NonLazyPointerAtom<A>::NonLazyPointerAtom(Writer<A>& writer, const char* targetName)
 
2421  : WriterAtom<A>(writer, Segment::fgDataSegment), fName(nonlazyPointerName(targetName)), fTarget(NULL)
 
2423         writer.fAllSynthesizedNonLazyPointers.push_back(this);
 
2424         fReferences.push_back(new WriterReference<A>(0, A::kPointer, targetName));
 
2427 template <typename A>
 
2428 const char* NonLazyPointerAtom<A>::nonlazyPointerName(const char* name)
 
2431         asprintf(&buf, "%s$non_lazy_pointer", name);
 
2435 template <typename A>
 
2436 void NonLazyPointerAtom<A>::copyRawContent(uint8_t buffer[]) const
 
2438         bzero(buffer, getSize());
 
2445 ObjectFile::Alignment StubAtom<ppc>::getAlignment() const
 
2451 ObjectFile::Alignment StubAtom<ppc64>::getAlignment() const
 
2457 ObjectFile::Alignment StubAtom<arm>::getAlignment() const
 
2463 StubAtom<ppc>::StubAtom(Writer<ppc>& writer, ObjectFile::Atom& target, bool forLazyDylib)
 
2464  : WriterAtom<ppc>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), 
 
2465         fTarget(target), fForLazyDylib(forLazyDylib)
 
2467         writer.fAllSynthesizedStubs.push_back(this);
 
2468         LazyPointerAtom<ppc>* lp;
 
2469         if (  fWriter.fOptions.prebind() ) {
 
2470                 // for prebound ppc, lazy pointer starts out pointing to target symbol's address
 
2471                 // if target is a weak definition within this linkage unit or zero if in some dylib
 
2472                 lp = new LazyPointerAtom<ppc>(writer, target, *this, forLazyDylib);
 
2475                 // for non-prebound ppc, lazy pointer starts out pointing to dyld_stub_binding_helper glue code
 
2476                 if ( forLazyDylib ) {
 
2477                         if ( writer.fDyldLazyDylibHelper == NULL )
 
2478                                 throw "symbol dyld_lazy_dylib_stub_binding_helper not defined (usually in lazydylib1.o)";
 
2479                         lp = new LazyPointerAtom<ppc>(writer, *writer.fDyldLazyDylibHelper, *this, forLazyDylib);
 
2482                         if ( writer.fDyldClassicHelperAtom == NULL )
 
2483                                 throw "symbol dyld_stub_binding_helper not defined (usually in crt1.o/dylib1.o/bundle1.o)";
 
2484                         lp = new LazyPointerAtom<ppc>(writer, *writer.fDyldClassicHelperAtom, *this, forLazyDylib);
 
2487         fKind = ( fWriter.fSlideable ? kStubPIC : kStubNoPIC );
 
2488         if ( fKind == kStubPIC ) {
 
2489                 // picbase is 8 bytes into atom
 
2490                 fReferences.push_back(new WriterReference<ppc>(12, ppc::kPICBaseHigh16, lp, 0, this, 8));
 
2491                 fReferences.push_back(new WriterReference<ppc>(20, ppc::kPICBaseLow16, lp, 0, this, 8));
 
2494                 fReferences.push_back(new WriterReference<ppc>(0, ppc::kAbsHigh16AddLow, lp));
 
2495                 fReferences.push_back(new WriterReference<ppc>(4, ppc::kAbsLow16, lp));
 
2500 StubAtom<ppc64>::StubAtom(Writer<ppc64>& writer, ObjectFile::Atom& target, bool forLazyDylib)
 
2501  : WriterAtom<ppc64>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), 
 
2502         fTarget(target), fForLazyDylib(forLazyDylib)
 
2504         writer.fAllSynthesizedStubs.push_back(this);
 
2506         LazyPointerAtom<ppc64>* lp;
 
2507         if ( forLazyDylib ) {
 
2508                 if ( writer.fDyldLazyDylibHelper == NULL )
 
2509                         throw "symbol dyld_lazy_dylib_stub_binding_helper not defined (usually in lazydylib1.o)";
 
2510                 lp = new LazyPointerAtom<ppc64>(writer, *writer.fDyldLazyDylibHelper, *this, forLazyDylib);
 
2513                 if ( writer.fDyldClassicHelperAtom == NULL )
 
2514                         throw "symbol dyld_stub_binding_helper not defined (usually in crt1.o/dylib1.o/bundle1.o)";
 
2515                 lp = new LazyPointerAtom<ppc64>(writer, *writer.fDyldClassicHelperAtom, *this, forLazyDylib);
 
2517         if ( fWriter.fSlideable || ((fWriter.fPageZeroAtom != NULL) && (fWriter.fPageZeroAtom->getSize() > 4096)) )
 
2521         if ( fKind == kStubPIC ) {
 
2522                 // picbase is 8 bytes into atom
 
2523                 fReferences.push_back(new WriterReference<ppc64>(12, ppc64::kPICBaseHigh16, lp, 0, this, 8));
 
2524                 fReferences.push_back(new WriterReference<ppc64>(20, ppc64::kPICBaseLow14, lp, 0, this, 8));
 
2527                 fReferences.push_back(new WriterReference<ppc64>(0, ppc64::kAbsHigh16AddLow, lp));
 
2528                 fReferences.push_back(new WriterReference<ppc64>(4, ppc64::kAbsLow14, lp));
 
2533 StubAtom<x86>::StubAtom(Writer<x86>& writer, ObjectFile::Atom& target, bool forLazyDylib)
 
2534  : WriterAtom<x86>(writer, (writer.fOptions.makeCompressedDyldInfo()|| forLazyDylib) ? Segment::fgTextSegment : Segment::fgImportSegment),
 
2535                                         fName(NULL), fTarget(target), fForLazyDylib(forLazyDylib)
 
2537         if ( writer.fOptions.makeCompressedDyldInfo() || forLazyDylib ) {
 
2539                 fName = stubName(target.getName());
 
2540                 LazyPointerAtom<x86>* lp = new LazyPointerAtom<x86>(writer, target, *this, forLazyDylib);
 
2541                 fReferences.push_back(new WriterReference<x86>(2, x86::kAbsolute32, lp));
 
2542                 writer.fAllSynthesizedStubs.push_back(this);
 
2546                 if ( &target == NULL ) 
 
2547                         asprintf((char**)&fName, "cache-line-crossing-stub %p", this);
 
2549                         fName = stubName(target.getName());
 
2550                         writer.fAllSynthesizedStubs.push_back(this);
 
2557 StubAtom<x86_64>::StubAtom(Writer<x86_64>& writer, ObjectFile::Atom& target, bool forLazyDylib)
 
2558  : WriterAtom<x86_64>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
 
2560         writer.fAllSynthesizedStubs.push_back(this);
 
2562         LazyPointerAtom<x86_64>* lp = new LazyPointerAtom<x86_64>(writer, target, *this, forLazyDylib);
 
2563         fReferences.push_back(new WriterReference<x86_64>(2, x86_64::kPCRel32, lp));
 
2567 StubAtom<arm>::StubAtom(Writer<arm>& writer, ObjectFile::Atom& target, bool forLazyDylib)
 
2568  : WriterAtom<arm>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
 
2570         writer.fAllSynthesizedStubs.push_back(this);
 
2571         if ( (writer.fDylibSymbolCountUpperBound < 900) 
 
2572                 && writer.fOptions.makeCompressedDyldInfo() 
 
2573                 && (writer.fOptions.outputKind() != Options::kDynamicLibrary) 
 
2574                 && !forLazyDylib ) {
 
2575                 // dylibs might have __TEXT and __DATA pulled apart to live in shared region
 
2576                 // if > 1000 stubs, the displacement to the lazy pointer my be > 12 bits.
 
2579         else if ( fWriter.fSlideable ) {
 
2585         LazyPointerAtom<arm>* lp = new LazyPointerAtom<arm>(writer, target, *this, forLazyDylib);
 
2588                         fReferences.push_back(new WriterReference<arm>(12, arm::kPointerDiff, lp, 0, this, 12));
 
2591                         fReferences.push_back(new WriterReference<arm>(8, arm::kReadOnlyPointer, lp));
 
2594                         fReferences.push_back(new WriterReference<arm>(0, arm::kPointerDiff12, lp, 0, this, 8));
 
2597                         throw "internal error";
 
2603 template <typename A>
 
2604 const char* StubAtom<A>::stubName(const char* name)
 
2607         asprintf(&buf, "%s$stub", name);
 
2612 uint64_t StubAtom<ppc>::getSize() const
 
2615         return ( (fKind == kStubPIC) ? 32 : 16 );
 
2619 uint64_t StubAtom<ppc64>::getSize() const
 
2621         return ( (fKind == kStubPIC)  ? 32 : 16 );
 
2626 uint64_t StubAtom<arm>::getSize() const
 
2636                         throw "internal error";
 
2641 uint64_t StubAtom<x86>::getSize() const
 
2649                         throw "internal error";
 
2654 uint64_t StubAtom<x86_64>::getSize() const
 
2660 ObjectFile::Alignment StubAtom<x86>::getAlignment() const
 
2666                         return 0; // special case x86 self-modifying stubs to be byte aligned
 
2668                         throw "internal error";
 
2673 void StubAtom<ppc64>::copyRawContent(uint8_t buffer[]) const
 
2675         if ( fKind == kStubPIC ) {
 
2676                 OSWriteBigInt32(&buffer [0], 0, 0x7c0802a6);    //      mflr r0
 
2677                 OSWriteBigInt32(&buffer[ 4], 0, 0x429f0005);    //  bcl 20,31,Lpicbase
 
2678                 OSWriteBigInt32(&buffer[ 8], 0, 0x7d6802a6);    // Lpicbase: mflr r11
 
2679                 OSWriteBigInt32(&buffer[12], 0, 0x3d6b0000);    //      addis r11,r11,ha16(L_fwrite$lazy_ptr-Lpicbase)
 
2680                 OSWriteBigInt32(&buffer[16], 0, 0x7c0803a6);    //      mtlr r0
 
2681                 OSWriteBigInt32(&buffer[20], 0, 0xe98b0001);    //      ldu r12,lo16(L_fwrite$lazy_ptr-Lpicbase)(r11)
 
2682                 OSWriteBigInt32(&buffer[24], 0, 0x7d8903a6);    //  mtctr r12
 
2683                 OSWriteBigInt32(&buffer[28], 0, 0x4e800420);    //  bctr
 
2686                 OSWriteBigInt32(&buffer[ 0], 0, 0x3d600000);    // lis r11,ha16(L_fwrite$lazy_ptr)
 
2687                 OSWriteBigInt32(&buffer[ 4], 0, 0xe98b0001);    // ldu r12,lo16(L_fwrite$lazy_ptr)(r11)
 
2688                 OSWriteBigInt32(&buffer[ 8], 0, 0x7d8903a6);    // mtctr r12
 
2689                 OSWriteBigInt32(&buffer[12], 0, 0x4e800420);    // bctr
 
2694 void StubAtom<ppc>::copyRawContent(uint8_t buffer[]) const
 
2696         if ( fKind == kStubPIC ) {
 
2697                 OSWriteBigInt32(&buffer[ 0], 0, 0x7c0802a6);    //      mflr r0
 
2698                 OSWriteBigInt32(&buffer[ 4], 0, 0x429f0005);    //  bcl 20,31,Lpicbase
 
2699                 OSWriteBigInt32(&buffer[ 8], 0, 0x7d6802a6);    // Lpicbase: mflr r11
 
2700                 OSWriteBigInt32(&buffer[12], 0, 0x3d6b0000);    //      addis r11,r11,ha16(L_fwrite$lazy_ptr-Lpicbase)
 
2701                 OSWriteBigInt32(&buffer[16], 0, 0x7c0803a6);    //      mtlr r0
 
2702                 OSWriteBigInt32(&buffer[20], 0, 0x858b0000);    //      lwzu r12,lo16(L_fwrite$lazy_ptr-Lpicbase)(r11)
 
2703                 OSWriteBigInt32(&buffer[24], 0, 0x7d8903a6);    //  mtctr r12
 
2704                 OSWriteBigInt32(&buffer[28], 0, 0x4e800420);    //  bctr
 
2707                 OSWriteBigInt32(&buffer[ 0], 0, 0x3d600000);    // lis r11,ha16(L_fwrite$lazy_ptr)
 
2708                 OSWriteBigInt32(&buffer[ 4], 0, 0x858b0000);    // lwzu r12,lo16(L_fwrite$lazy_ptr)(r11)
 
2709                 OSWriteBigInt32(&buffer[ 8], 0, 0x7d8903a6);    // mtctr r12
 
2710                 OSWriteBigInt32(&buffer[12], 0, 0x4e800420);    // bctr
 
2715 void StubAtom<x86>::copyRawContent(uint8_t buffer[]) const
 
2719                         buffer[0] = 0xFF;               // jmp *foo$lazy_pointer
 
2727                         if ( fWriter.fOptions.prebind() ) {
 
2728                                 uint32_t address = this->getAddress();
 
2729                                 int32_t rel32 = 0 - (address+5); 
 
2731                                 buffer[1] = rel32 & 0xFF;
 
2732                                 buffer[2] = (rel32 >> 8) & 0xFF;
 
2733                                 buffer[3] = (rel32 >> 16) & 0xFF;
 
2734                                 buffer[4] = (rel32 >> 24) & 0xFF;
 
2745                         throw "internal error";
 
2750 void StubAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
 
2752         buffer[0] = 0xFF;               // jmp *foo$lazy_pointer(%rip)
 
2761 void StubAtom<arm>::copyRawContent(uint8_t buffer[]) const
 
2765                         OSWriteLittleInt32(&buffer[ 0], 0, 0xe59fc004); //      ldr ip, pc + 12
 
2766                         OSWriteLittleInt32(&buffer[ 4], 0, 0xe08fc00c); //      add ip, pc, ip
 
2767                         OSWriteLittleInt32(&buffer[ 8], 0, 0xe59cf000); //      ldr pc, [ip]
 
2768                         OSWriteLittleInt32(&buffer[12], 0, 0x00000000); //      .long L_foo$lazy_ptr - (L1$scv + 8)
 
2771                         OSWriteLittleInt32(&buffer[ 0], 0, 0xe59fc000); //      ldr ip, [pc, #0]
 
2772                         OSWriteLittleInt32(&buffer[ 4], 0, 0xe59cf000); //      ldr pc, [ip]
 
2773                         OSWriteLittleInt32(&buffer[ 8], 0, 0x00000000); //      .long   L_foo$lazy_ptr
 
2776                         OSWriteLittleInt32(&buffer[ 0], 0, 0xE59FF000);//       ldr     pc, [pc, #foo$lazy_ptr]
 
2779                         throw "internal error";
 
2783 // x86_64 stubs are 6 bytes 
 
2785 ObjectFile::Alignment StubAtom<x86_64>::getAlignment() const
 
2791 const char*     StubAtom<ppc>::getSectionName() const
 
2793         return ( (fKind == kStubPIC) ? "__picsymbolstub1" : "__symbol_stub1");
 
2797 const char*     StubAtom<ppc64>::getSectionName() const
 
2799         return ( (fKind == kStubPIC) ? "__picsymbolstub1" : "__symbol_stub1");
 
2803 const char*     StubAtom<arm>::getSectionName() const
 
2807                         return "__picsymbolstub4";
 
2809                         return "__symbol_stub4";
 
2811                         return "__symbolstub1";
 
2813                         throw "internal error";
 
2818 const char*     StubAtom<x86>::getSectionName() const
 
2822                         return "__symbol_stub";
 
2824                         return "__jump_table";
 
2826                         throw "internal error";
 
2833 struct AtomByNameSorter
 
2835      bool operator()(ObjectFile::Atom* left, ObjectFile::Atom* right)
 
2837           return (strcmp(left->getName(), right->getName()) < 0);
 
2841 template <typename P>
 
2842 struct ExternalRelocSorter
 
2844      bool operator()(const macho_relocation_info<P>& left, const macho_relocation_info<P>& right)
 
2846                 // sort first by symbol number
 
2847                 if ( left.r_symbolnum() != right.r_symbolnum() )
 
2848                         return (left.r_symbolnum() < right.r_symbolnum());
 
2849                 // then sort all uses of the same symbol by address
 
2850                 return (left.r_address() < right.r_address());
 
2855 template <typename A>
 
2856 Writer<A>::Writer(const char* path, Options& options, std::vector<ExecutableFile::DyLibUsed>& dynamicLibraries)
 
2857         : ExecutableFile::Writer(dynamicLibraries), fFilePath(strdup(path)), fOptions(options), 
 
2858           fAllAtoms(NULL), fStabs(NULL), fRegularDefAtomsThatOverrideADylibsWeakDef(NULL), fLoadCommandsSection(NULL),
 
2859           fLoadCommandsSegment(NULL), fMachHeaderAtom(NULL), fEncryptionLoadCommand(NULL), fSegmentCommands(NULL), 
 
2860           fSymbolTableCommands(NULL), fHeaderPadding(NULL), fUnwindInfoAtom(NULL),
 
2861           fUUIDAtom(NULL), fPadSegmentInfo(NULL), fEntryPoint( NULL), 
 
2862           fDyldClassicHelperAtom(NULL), fDyldCompressedHelperAtom(NULL), fDyldLazyDylibHelper(NULL),
 
2863           fSectionRelocationsAtom(NULL),   fCompressedRebaseInfoAtom(NULL),  fCompressedBindingInfoAtom(NULL),
 
2864           fCompressedWeakBindingInfoAtom(NULL), fCompressedLazyBindingInfoAtom(NULL), fCompressedExportInfoAtom(NULL),
 
2865           fLocalRelocationsAtom(NULL), fExternalRelocationsAtom(NULL),
 
2866           fSymbolTableAtom(NULL), fSplitCodeToDataContentAtom(NULL), fIndirectTableAtom(NULL), fModuleInfoAtom(NULL), 
 
2867           fStringsAtom(NULL), fPageZeroAtom(NULL), fFastStubGOTAtom(NULL), fSymbolTable(NULL), fSymbolTableCount(0), 
 
2868           fSymbolTableStabsCount(0), fSymbolTableLocalCount(0), fSymbolTableExportCount(0), fSymbolTableImportCount(0), 
 
2869           fLargestAtomSize(1), 
 
2870           fEmitVirtualSections(false), fHasWeakExports(false), fReferencesWeakImports(false), 
 
2871           fCanScatter(false), fWritableSegmentPastFirst4GB(false), fNoReExportedDylibs(false), 
 
2872           fBiggerThanTwoGigs(false), fSlideable(false), fHasThumbBranches(false),
 
2873           fFirstWritableSegment(NULL), fAnonNameIndex(1000)
 
2875         switch ( fOptions.outputKind() ) {
 
2876                 case Options::kDynamicExecutable:
 
2877                 case Options::kStaticExecutable:
 
2878                         if ( fOptions.zeroPageSize() != 0 )
 
2879                                 fWriterSynthesizedAtoms.push_back(fPageZeroAtom = new PageZeroAtom<A>(*this));
 
2880                         if ( fOptions.outputKind() == Options::kDynamicExecutable )
 
2881                                 fWriterSynthesizedAtoms.push_back(new DsoHandleAtom<A>(*this));
 
2882                         fWriterSynthesizedAtoms.push_back(fMachHeaderAtom = new MachHeaderAtom<A>(*this));
 
2883                         fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
 
2884                         if ( fOptions.makeCompressedDyldInfo() ) 
 
2885                                 fWriterSynthesizedAtoms.push_back(new DyldInfoLoadCommandsAtom<A>(*this));
 
2886                         fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
 
2887                         if ( fOptions.outputKind() == Options::kDynamicExecutable )
 
2888                                 fWriterSynthesizedAtoms.push_back(new DyldLoadCommandsAtom<A>(*this));
 
2889                         fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
 
2890                         fWriterSynthesizedAtoms.push_back(new ThreadsLoadCommandsAtom<A>(*this));
 
2891                         if ( fOptions.hasCustomStack() )
 
2892                                 fWriterSynthesizedAtoms.push_back(new CustomStackAtom<A>(*this));
 
2893                         fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
 
2894                         if ( fOptions.needsUnwindInfoSection() )
 
2895                                 fWriterSynthesizedAtoms.push_back(fUnwindInfoAtom = new UnwindInfoAtom<A>(*this));
 
2896                         fWriterSynthesizedAtoms.push_back(fSectionRelocationsAtom = new SectionRelocationsLinkEditAtom<A>(*this));
 
2897                         if ( fOptions.makeCompressedDyldInfo() ) {
 
2898                                 fWriterSynthesizedAtoms.push_back(fCompressedRebaseInfoAtom = new CompressedRebaseInfoLinkEditAtom<A>(*this));
 
2899                                 fWriterSynthesizedAtoms.push_back(fCompressedBindingInfoAtom = new CompressedBindingInfoLinkEditAtom<A>(*this));
 
2900                                 fWriterSynthesizedAtoms.push_back(fCompressedWeakBindingInfoAtom = new CompressedWeakBindingInfoLinkEditAtom<A>(*this));
 
2901                                 fWriterSynthesizedAtoms.push_back(fCompressedLazyBindingInfoAtom = new CompressedLazyBindingInfoLinkEditAtom<A>(*this));
 
2902                                 fWriterSynthesizedAtoms.push_back(fCompressedExportInfoAtom = new CompressedExportInfoLinkEditAtom<A>(*this));
 
2904                         if ( fOptions.makeClassicDyldInfo() ) 
 
2905                                 fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
 
2906                         fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
 
2907                         if ( fOptions.makeClassicDyldInfo() ) 
 
2908                                 fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
 
2909                         fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
 
2910                         fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
 
2912                 case Options::kPreload:
 
2913                         fWriterSynthesizedAtoms.push_back(fMachHeaderAtom = new MachHeaderAtom<A>(*this));
 
2914                         fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
 
2915                         fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
 
2916                         fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
 
2917                         fWriterSynthesizedAtoms.push_back(new ThreadsLoadCommandsAtom<A>(*this));
 
2918                         fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
 
2919                         fWriterSynthesizedAtoms.push_back(fSectionRelocationsAtom = new SectionRelocationsLinkEditAtom<A>(*this));
 
2920                         fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
 
2921                         fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
 
2922                         fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
 
2923                         fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
 
2924                         fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
 
2926                 case Options::kDynamicLibrary:
 
2927                 case Options::kDynamicBundle:
 
2928                         fWriterSynthesizedAtoms.push_back(new DsoHandleAtom<A>(*this));
 
2929                 case Options::kKextBundle:
 
2930                         fWriterSynthesizedAtoms.push_back(fMachHeaderAtom = new MachHeaderAtom<A>(*this));
 
2931                         fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
 
2932                         if ( fOptions.outputKind() == Options::kDynamicLibrary ) {
 
2933                                 fWriterSynthesizedAtoms.push_back(new DylibIDLoadCommandsAtom<A>(*this));
 
2934                                 if ( fOptions.initFunctionName() != NULL )
 
2935                                         fWriterSynthesizedAtoms.push_back(new RoutinesLoadCommandsAtom<A>(*this));
 
2937                         fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
 
2938                         if ( fOptions.makeCompressedDyldInfo() )
 
2939                                 fWriterSynthesizedAtoms.push_back(new DyldInfoLoadCommandsAtom<A>(*this));
 
2940                         fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
 
2941                         if ( fOptions.sharedRegionEligible() )
 
2942                                 fWriterSynthesizedAtoms.push_back(new SegmentSplitInfoLoadCommandsAtom<A>(*this));
 
2943                         fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
 
2944                         if ( fOptions.needsUnwindInfoSection() )
 
2945                                 fWriterSynthesizedAtoms.push_back(fUnwindInfoAtom = new UnwindInfoAtom<A>(*this));
 
2946                         fWriterSynthesizedAtoms.push_back(fSectionRelocationsAtom = new SectionRelocationsLinkEditAtom<A>(*this));
 
2947                         if ( fOptions.makeCompressedDyldInfo() ) {
 
2948                                 fWriterSynthesizedAtoms.push_back(fCompressedRebaseInfoAtom = new CompressedRebaseInfoLinkEditAtom<A>(*this));
 
2949                                 fWriterSynthesizedAtoms.push_back(fCompressedBindingInfoAtom = new CompressedBindingInfoLinkEditAtom<A>(*this));
 
2950                                 fWriterSynthesizedAtoms.push_back(fCompressedWeakBindingInfoAtom = new CompressedWeakBindingInfoLinkEditAtom<A>(*this));
 
2951                                 fWriterSynthesizedAtoms.push_back(fCompressedLazyBindingInfoAtom = new CompressedLazyBindingInfoLinkEditAtom<A>(*this));
 
2952                                 fWriterSynthesizedAtoms.push_back(fCompressedExportInfoAtom = new CompressedExportInfoLinkEditAtom<A>(*this));
 
2954                         if ( fOptions.makeClassicDyldInfo() ) 
 
2955                                 fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
 
2956                         if ( fOptions.sharedRegionEligible() ) {
 
2957                                 fWriterSynthesizedAtoms.push_back(fSplitCodeToDataContentAtom = new SegmentSplitInfoContentAtom<A>(*this));
 
2959                         fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
 
2960                         if ( fOptions.makeClassicDyldInfo() ) 
 
2961                                 fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
 
2962                         if ( fOptions.outputKind() != Options::kKextBundle ) 
 
2963                                 fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
 
2964                         if ( this->needsModuleTable() )
 
2965                                 fWriterSynthesizedAtoms.push_back(fModuleInfoAtom = new ModuleInfoLinkEditAtom<A>(*this));
 
2966                         fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
 
2968                 case Options::kObjectFile:
 
2969                         fWriterSynthesizedAtoms.push_back(fMachHeaderAtom = new MachHeaderAtom<A>(*this));
 
2970                         fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
 
2971                         fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
 
2972                         fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
 
2973                         fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
 
2974                         fWriterSynthesizedAtoms.push_back(fSectionRelocationsAtom = new SectionRelocationsLinkEditAtom<A>(*this));
 
2975                         fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
 
2976                         fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
 
2977                         fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
 
2978                         fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
 
2979                         fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
 
2981                 case Options::kDyld:
 
2982                         fWriterSynthesizedAtoms.push_back(new DsoHandleAtom<A>(*this));
 
2983                         fWriterSynthesizedAtoms.push_back(fMachHeaderAtom = new MachHeaderAtom<A>(*this));
 
2984                         fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
 
2985                         fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
 
2986                         fWriterSynthesizedAtoms.push_back(new DyldLoadCommandsAtom<A>(*this));
 
2987                         fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
 
2988                         fWriterSynthesizedAtoms.push_back(new ThreadsLoadCommandsAtom<A>(*this));
 
2989                         fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
 
2990                         if ( fOptions.needsUnwindInfoSection() )
 
2991                                 fWriterSynthesizedAtoms.push_back(fUnwindInfoAtom = new UnwindInfoAtom<A>(*this));
 
2992                         fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
 
2993                         fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
 
2994                         fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
 
2995                         fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
 
2996                         fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
 
3000         // add extra commmands
 
3001         bool hasReExports = false;
 
3002         uint32_t ordinal = 1;
 
3003         switch ( fOptions.outputKind() ) {
 
3004                 case Options::kDynamicExecutable:
 
3005                         if ( fOptions.makeEncryptable() ) {
 
3006                                 fEncryptionLoadCommand = new EncryptionLoadCommandsAtom<A>(*this);
 
3007                                 fWriterSynthesizedAtoms.push_back(fEncryptionLoadCommand);
 
3010                 case Options::kDynamicLibrary:
 
3011                 case Options::kDynamicBundle:
 
3013                                 // add dylib load command atoms for all dynamic libraries
 
3014                                 const unsigned int libCount = dynamicLibraries.size();
 
3015                                 for (unsigned int i=0; i < libCount; ++i) {
 
3016                                         ExecutableFile::DyLibUsed& dylibInfo = dynamicLibraries[i];
 
3017                                         //fprintf(stderr, "dynamicLibraries[%d]: reader=%p, %s, install=%s\n", i, dylibInfo.reader, dylibInfo.reader->getPath(), dylibInfo.reader->getInstallPath() );
 
3019                                         if ( dylibInfo.options.fReExport ) {
 
3020                                                 hasReExports = true;
 
3023                                                 const char* parentUmbrella = dylibInfo.reader->parentUmbrella();
 
3024                                                 if ( (parentUmbrella != NULL) && (fOptions.outputKind() == Options::kDynamicLibrary) ) {
 
3025                                                         const char* thisIDLastSlash = strrchr(fOptions.installPath(), '/');
 
3026                                                         if ( (thisIDLastSlash != NULL) && (strcmp(&thisIDLastSlash[1], parentUmbrella) == 0) )
 
3027                                                                 hasReExports = true;
 
3031                                         if ( dylibInfo.options.fWeakImport ) {
 
3032                                                 fForcedWeakImportReaders.insert(dylibInfo.reader);
 
3035                                         if ( dylibInfo.options.fBundleLoader ) {
 
3036                                                 fLibraryToOrdinal[dylibInfo.reader] = EXECUTABLE_ORDINAL;
 
3039                                                 // see if a DylibLoadCommandsAtom has already been created for this install path
 
3040                                                 bool newDylib = true;
 
3041                                                 const char* dylibInstallPath = dylibInfo.reader->getInstallPath();
 
3042                                                 for (unsigned int seenLib=0; seenLib < i; ++seenLib) {
 
3043                                                         ExecutableFile::DyLibUsed& seenDylibInfo = dynamicLibraries[seenLib];
 
3044                                                         if ( !seenDylibInfo.options.fBundleLoader ) {
 
3045                                                                 const char* seenDylibInstallPath = seenDylibInfo.reader->getInstallPath();
 
3046                                                                 if ( strcmp(seenDylibInstallPath, dylibInstallPath) == 0 ) {
 
3047                                                                         fLibraryToOrdinal[dylibInfo.reader] = fLibraryToOrdinal[seenDylibInfo.reader];
 
3048                                                                         fLibraryToLoadCommand[dylibInfo.reader] = fLibraryToLoadCommand[seenDylibInfo.reader]; 
 
3049                                                                         fLibraryAliases[dylibInfo.reader] = seenDylibInfo.reader;
 
3057                                                         // assign new ordinal and check for other paired load commands
 
3058                                                         fLibraryToOrdinal[dylibInfo.reader] = ordinal++;
 
3059                                                         DylibLoadCommandsAtom<A>* dyliblc = new DylibLoadCommandsAtom<A>(*this, dylibInfo);
 
3060                                                         fLibraryToLoadCommand[dylibInfo.reader] = dyliblc;
 
3061                                                         fWriterSynthesizedAtoms.push_back(dyliblc);
 
3062                                                         if ( dylibInfo.options.fReExport 
 
3063                                                                 && !fOptions.useSimplifiedDylibReExports() 
 
3064                                                                 && (fOptions.outputKind() == Options::kDynamicLibrary) ) {
 
3065                                                                 // see if child has sub-framework that is this
 
3066                                                                 bool isSubFramework = false;
 
3067                                                                 const char* childInUmbrella = dylibInfo.reader->parentUmbrella();
 
3068                                                                 if ( childInUmbrella != NULL ) {
 
3069                                                                         const char* myLeaf = strrchr(fOptions.installPath(), '/');
 
3070                                                                         if ( myLeaf != NULL ) {
 
3071                                                                                 if ( strcmp(childInUmbrella, &myLeaf[1]) == 0 )
 
3072                                                                                         isSubFramework = true;
 
3075                                                                 // LC_SUB_FRAMEWORK is in child, so do nothing in parent 
 
3076                                                                 if ( ! isSubFramework ) {
 
3077                                                                         // this dylib also needs a sub_x load command
 
3078                                                                         bool isFrameworkReExport = false;
 
3079                                                                         const char* lastSlash = strrchr(dylibInstallPath, '/');
 
3080                                                                         if ( lastSlash != NULL ) {
 
3081                                                                                 char frameworkName[strlen(lastSlash)+20];
 
3082                                                                                 sprintf(frameworkName, "/%s.framework/", &lastSlash[1]);
 
3083                                                                                 isFrameworkReExport = (strstr(dylibInstallPath, frameworkName) != NULL);
 
3085                                                                         if ( isFrameworkReExport ) {
 
3086                                                                                 // needs a LC_SUB_UMBRELLA command
 
3087                                                                                 fWriterSynthesizedAtoms.push_back(new SubUmbrellaLoadCommandsAtom<A>(*this, &lastSlash[1]));
 
3090                                                                                 // needs a LC_SUB_LIBRARY command
 
3091                                                                                 const char* nameStart = &lastSlash[1];
 
3092                                                                                 if ( lastSlash == NULL )
 
3093                                                                                         nameStart = dylibInstallPath;
 
3094                                                                                 int len = strlen(nameStart);
 
3095                                                                                 const char* dot = strchr(nameStart, '.');
 
3097                                                                                         len = dot - nameStart;
 
3098                                                                                 fWriterSynthesizedAtoms.push_back(new SubLibraryLoadCommandsAtom<A>(*this, nameStart, len));
 
3105                                 // add umbrella command if needed
 
3106                                 if ( fOptions.umbrellaName() != NULL ) {
 
3107                                         fWriterSynthesizedAtoms.push_back(new UmbrellaLoadCommandsAtom<A>(*this, fOptions.umbrellaName()));
 
3109                                 // add allowable client commands if used
 
3110                                 std::vector<const char*>& allowableClients = fOptions.allowableClients();
 
3111                                 for (std::vector<const char*>::iterator it=allowableClients.begin(); it != allowableClients.end(); ++it)
 
3112                                         fWriterSynthesizedAtoms.push_back(new AllowableClientLoadCommandsAtom<A>(*this, *it));
 
3115                 case Options::kStaticExecutable:
 
3116                 case Options::kObjectFile:
 
3117                 case Options::kDyld:
 
3118                 case Options::kPreload:
 
3119                 case Options::kKextBundle:
 
3122         fNoReExportedDylibs = !hasReExports;
 
3124         // add any rpath load commands
 
3125         for(std::vector<const char*>::const_iterator it=fOptions.rpaths().begin(); it != fOptions.rpaths().end(); ++it) {
 
3126                 fWriterSynthesizedAtoms.push_back(new RPathLoadCommandsAtom<A>(*this, *it));
 
3129         // set up fSlideable
 
3130         switch ( fOptions.outputKind() ) {
 
3131                 case Options::kObjectFile:
 
3132                 case Options::kStaticExecutable:
 
3135                 case Options::kDynamicExecutable:
 
3136                         fSlideable = fOptions.positionIndependentExecutable();
 
3138                 case Options::kDyld:
 
3139                 case Options::kDynamicLibrary:
 
3140                 case Options::kDynamicBundle:
 
3141                 case Options::kPreload:
 
3142                 case Options::kKextBundle:
 
3147         //fprintf(stderr, "ordinals table:\n");
 
3148         //for (std::map<class ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {
 
3149         //      fprintf(stderr, "%d <== %s\n", it->second, it->first->getPath());
 
3153 template <typename A>
 
3154 Writer<A>::~Writer()
 
3156         if ( fFilePath != NULL )
 
3157                 free((void*)fFilePath);
 
3158         if ( fSymbolTable != NULL )
 
3159                 delete [] fSymbolTable;
 
3163 // for ppc64, -mdynamic-no-pic only works in low 2GB, so we might need to split the zeropage into two segments
 
3164 template <>bool Writer<ppc64>::mightNeedPadSegment() { return (fOptions.zeroPageSize() >= 0x80000000ULL); }
 
3165 template <typename A> bool Writer<A>::mightNeedPadSegment() { return false; }
 
3168 template <typename A>
 
3169 ObjectFile::Atom* Writer<A>::getUndefinedProxyAtom(const char* name)
 
3171         if ( fOptions.outputKind() == Options::kKextBundle ) {
 
3172                 return new UndefinedSymbolProxyAtom<A>(*this, name);
 
3174         else if ( fOptions.outputKind() == Options::kObjectFile ) {
 
3175                 // when doing -r -exported_symbols_list, don't create proxy for a symbol
 
3176                 // that is supposed to be exported.  We want an error instead
 
3177                 // <rdar://problem/5062685> ld does not report error when -r is used and exported symbols are not defined.
 
3178                 if ( fOptions.hasExportMaskList() && fOptions.shouldExport(name) )
 
3181                         return new UndefinedSymbolProxyAtom<A>(*this, name);
 
3183         else if ( (fOptions.undefinedTreatment() != Options::kUndefinedError) || fOptions.allowedUndefined(name) )  
 
3184                 return new UndefinedSymbolProxyAtom<A>(*this, name);
 
3189 template <typename A>
 
3190 uint8_t Writer<A>::ordinalForLibrary(ObjectFile::Reader* lib)
 
3192         // flat namespace images use zero for all ordinals
 
3193         if (  fOptions.nameSpace() != Options::kTwoLevelNameSpace )
 
3196         // is an UndefinedSymbolProxyAtom
 
3198                 if ( fOptions.nameSpace() == Options::kTwoLevelNameSpace )
 
3199                         return DYNAMIC_LOOKUP_ORDINAL;
 
3201         std::map<class ObjectFile::Reader*, uint32_t>::iterator pos = fLibraryToOrdinal.find(lib);
 
3202         if ( pos != fLibraryToOrdinal.end() )
 
3205         throw "can't find ordinal for imported symbol";
 
3208 template <typename A>
 
3209 bool Writer<A>::targetRequiresWeakBinding(const ObjectFile::Atom& target)
 
3211         switch ( target.getDefinitionKind() ) {
 
3212                 case ObjectFile::Atom::kExternalWeakDefinition:
 
3213                 case ObjectFile::Atom::kWeakDefinition:
 
3215                 case ObjectFile::Atom::kExternalDefinition:
 
3216                 case ObjectFile::Atom::kAbsoluteSymbol:
 
3217                 case ObjectFile::Atom::kRegularDefinition:
 
3218                 case ObjectFile::Atom::kTentativeDefinition:
 
3224 template <typename A>
 
3225 int Writer<A>::compressedOrdinalForImortedAtom(ObjectFile::Atom* target)
 
3227         // flat namespace images use zero for all ordinals
 
3228         if (  fOptions.nameSpace() != Options::kTwoLevelNameSpace )
 
3229                 return BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
 
3231         // is an UndefinedSymbolProxyAtom
 
3232         ObjectFile::Reader* lib = target->getFile();
 
3234                 if ( fOptions.nameSpace() == Options::kTwoLevelNameSpace )
 
3235                         return BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
 
3237         std::map<class ObjectFile::Reader*, uint32_t>::iterator pos;
 
3238         switch ( target->getDefinitionKind() ) {
 
3239                 case ObjectFile::Atom::kExternalDefinition:
 
3240                 case ObjectFile::Atom::kExternalWeakDefinition:
 
3241                         pos = fLibraryToOrdinal.find(lib);
 
3242                         if ( pos != fLibraryToOrdinal.end() ) {
 
3243                                 if ( pos->second == EXECUTABLE_ORDINAL )
 
3244                                         return BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE;
 
3249                 case ObjectFile::Atom::kWeakDefinition:
 
3250                         throw "compressedOrdinalForImortedAtom() should not have been called on a weak definition";
 
3251                 case ObjectFile::Atom::kAbsoluteSymbol:
 
3252                 case ObjectFile::Atom::kRegularDefinition:
 
3253                 case ObjectFile::Atom::kTentativeDefinition:
 
3254                         return BIND_SPECIAL_DYLIB_SELF;
 
3257         throw "can't find ordinal for imported symbol";
 
3261 template <typename A>
 
3262 ObjectFile::Atom& Writer<A>::makeObjcInfoAtom(ObjectFile::Reader::ObjcConstraint objcContraint, bool objcReplacementClasses)
 
3264         return *(new ObjCInfoAtom<A>(*this, objcContraint, objcReplacementClasses));
 
3267 template <typename A>
 
3268 void Writer<A>::addSynthesizedAtoms(const std::vector<class ObjectFile::Atom*>& existingAtoms,
 
3269                                                                   class ObjectFile::Atom* dyldClassicHelperAtom,
 
3270                                                                   class ObjectFile::Atom* dyldCompressedHelperAtom,
 
3271                                                                   class ObjectFile::Atom* dyldLazyDylibHelperAtom,
 
3272                                                                   bool biggerThanTwoGigs,
 
3273                                                                         uint32_t dylibSymbolCount,
 
3274                                                                         std::vector<class ObjectFile::Atom*>& newAtoms)
 
3276         fDyldClassicHelperAtom = dyldClassicHelperAtom;
 
3277         fDyldCompressedHelperAtom = dyldCompressedHelperAtom;
 
3278         fDyldLazyDylibHelper = dyldLazyDylibHelperAtom;
 
3279         fBiggerThanTwoGigs = biggerThanTwoGigs;
 
3280         fDylibSymbolCountUpperBound = dylibSymbolCount;
 
3282         // create inter-library stubs
 
3283         synthesizeStubs(existingAtoms, newAtoms);
 
3287 template <typename A>
 
3288 uint64_t Writer<A>::write(std::vector<class ObjectFile::Atom*>& atoms,
 
3289                                                   std::vector<class ObjectFile::Reader::Stab>& stabs,
 
3290                                                   class ObjectFile::Atom* entryPointAtom, 
 
3291                                                   bool createUUID, bool canScatter, ObjectFile::Reader::CpuConstraint cpuConstraint,
 
3292                                                   std::set<const class ObjectFile::Atom*>& atomsThatOverrideWeak,
 
3293                                                   bool hasExternalWeakDefinitions)
 
3297         fEntryPoint = entryPointAtom;
 
3298         fCanScatter = canScatter;
 
3299         fCpuConstraint = cpuConstraint;
 
3300         fHasWeakExports = hasExternalWeakDefinitions; // dyld needs to search this image as if it had weak exports
 
3301         fRegularDefAtomsThatOverrideADylibsWeakDef = &atomsThatOverrideWeak;
 
3305                 // Set for create UUID
 
3307                         fUUIDAtom->generate();
 
3309                 // remove uneeded dylib load commands
 
3310                 optimizeDylibReferences();
 
3312                 // check for mdynamic-no-pic codegen
 
3313                 scanForAbsoluteReferences();
 
3315                 // create table of unwind info
 
3316                 synthesizeUnwindInfoTable();
 
3318                 // create SegmentInfo and SectionInfo objects and assign all atoms to a section
 
3319                 partitionIntoSections();
 
3321                 // segment load command can now be sized and padding can be set
 
3322                 adjustLoadCommandsAndPadding();
 
3324                 // assign each section a file offset
 
3325                 assignFileOffsets();
 
3327                 // if need to add branch islands, reassign file offsets
 
3328                 if ( addBranchIslands() )
 
3329                         assignFileOffsets();
 
3331                 // now that addresses are assigned, create unwind info 
 
3332                 if ( fUnwindInfoAtom != NULL ) {
 
3333                         fUnwindInfoAtom->generate();
 
3335                         adjustLoadCommandsAndPadding();
 
3336                         assignFileOffsets();
 
3339                 // make spit-seg info now that all atoms exist
 
3340                 createSplitSegContent();
 
3342                 // build symbol table and relocations
 
3345                 // write map file if requested
 
3349                 return writeAtoms();
 
3351                 // clean up if any errors
 
3352                 (void)unlink(fFilePath);
 
3357 template <typename A>
 
3358 void Writer<A>::buildLinkEdit()
 
3360         this->collectExportedAndImportedAndLocalAtoms();
 
3361         this->buildSymbolTable();
 
3362         this->buildFixups();
 
3363         this->adjustLinkEditSections();
 
3368 template <typename A>
 
3369 uint64_t Writer<A>::getAtomLoadAddress(const ObjectFile::Atom* atom)
 
3371         return atom->getAddress();
 
3372 //      SectionInfo* info = (SectionInfo*)atom->getSection();
 
3373 //      return info->getBaseAddress() + atom->getSectionOffset();
 
3377 bool Writer<x86_64>::stringsNeedLabelsInObjects()
 
3382 template <typename A>
 
3383 bool Writer<A>::stringsNeedLabelsInObjects()
 
3388 template <typename A>
 
3389 const char* Writer<A>::symbolTableName(const ObjectFile::Atom* atom)
 
3391         static unsigned int counter = 0;
 
3393         if ( stringsNeedLabelsInObjects() 
 
3394                 && (atom->getContentType() == ObjectFile::Atom::kCStringType) 
 
3395                 && (atom->getDefinitionKind() == ObjectFile::Atom::kWeakDefinition) )
 
3396                 asprintf((char**)&name, "LC%u", counter++);
 
3398                 name = atom->getName();
 
3400         return atom->getName();
 
3403 template <typename A>
 
3404 void Writer<A>::setExportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry)
 
3407         entry->set_n_strx(this->fStringsAtom->add(this->symbolTableName(atom)));
 
3410         if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableInAsAbsolute ) {
 
3411                 entry->set_n_type(N_EXT | N_ABS);
 
3414                 entry->set_n_type(N_EXT | N_SECT);
 
3415                 if ( (atom->getScope() == ObjectFile::Atom::scopeLinkageUnit) && (fOptions.outputKind() == Options::kObjectFile) ) {
 
3416                         if ( fOptions.keepPrivateExterns() )
 
3417                                 entry->set_n_type(N_EXT | N_SECT | N_PEXT);
 
3421         // set n_sect (section number of implementation )
 
3422         uint8_t sectionIndex = atom->getSection()->getIndex();
 
3423         entry->set_n_sect(sectionIndex);
 
3425         // the __mh_execute_header is magic and must be an absolute symbol
 
3426         if ( (sectionIndex==0) 
 
3427                 && (fOptions.outputKind() == Options::kDynamicExecutable)
 
3428                 && (atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableInAndNeverStrip ))
 
3429                 entry->set_n_type(N_EXT | N_ABS);
 
3433     if ( atom->isThumb() )
 
3434         desc |= N_ARM_THUMB_DEF;
 
3435     if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableInAndNeverStrip )
 
3436         desc |= REFERENCED_DYNAMICALLY;
 
3437     if ( atom->dontDeadStrip() && (fOptions.outputKind() == Options::kObjectFile) )
 
3438         desc |= N_NO_DEAD_STRIP;
 
3439     if ( atom->getDefinitionKind() == ObjectFile::Atom::kWeakDefinition ) {
 
3441         fHasWeakExports = true;
 
3443         entry->set_n_desc(desc);
 
3445         // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
 
3446         if ( atom->getDefinitionKind() == ObjectFile::Atom::kAbsoluteSymbol ) 
 
3447                 entry->set_n_value(atom->getSectionOffset());
 
3449                 entry->set_n_value(this->getAtomLoadAddress(atom));
 
3452 template <typename A>
 
3453 void Writer<A>::setImportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry)
 
3456         entry->set_n_strx(this->fStringsAtom->add(atom->getName()));
 
3459         if ( fOptions.outputKind() == Options::kObjectFile ) {
 
3460                 if ( (atom->getScope() == ObjectFile::Atom::scopeLinkageUnit) 
 
3461                                 && (atom->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition) )
 
3462                         entry->set_n_type(N_UNDF | N_EXT | N_PEXT);
 
3464                         entry->set_n_type(N_UNDF | N_EXT);
 
3467                 if ( fOptions.prebind() )
 
3468                         entry->set_n_type(N_PBUD | N_EXT);
 
3470                         entry->set_n_type(N_UNDF | N_EXT);
 
3474         entry->set_n_sect(0);
 
3477         if ( fOptions.outputKind() != Options::kObjectFile ) {
 
3478                 // set n_desc ( high byte is library ordinal, low byte is reference type )
 
3479                 std::map<const ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fStubsMap.find(atom);
 
3480                 if ( pos != fStubsMap.end() || ( strncmp(atom->getName(), ".objc_class_name_", 17) == 0) )
 
3481                         desc = REFERENCE_FLAG_UNDEFINED_LAZY;
 
3483                         desc = REFERENCE_FLAG_UNDEFINED_NON_LAZY;
 
3485                         uint8_t ordinal = this->ordinalForLibrary(atom->getFile());
 
3486                         //fprintf(stderr, "ordinal=%u from reader=%p for symbol=%s\n", ordinal, atom->getFile(), atom->getName());
 
3487                         SET_LIBRARY_ORDINAL(desc, ordinal);
 
3489                 catch (const char* msg) {
 
3490                         throwf("%s %s from %s", msg, atom->getDisplayName(), atom->getFile()->getPath());
 
3493         else if ( atom->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition ) {
 
3494                 uint8_t align = atom->getAlignment().powerOf2;
 
3495                 // always record custom alignment of common symbols to match what compiler does
 
3496                 SET_COMM_ALIGN(desc, align);
 
3498         if ( atom->isThumb() )
 
3499                 desc |= N_ARM_THUMB_DEF;
 
3500         if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableInAndNeverStrip )
 
3501                 desc |= REFERENCED_DYNAMICALLY;
 
3502         if ( ( fOptions.outputKind() != Options::kObjectFile) && (atom->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
 
3503                 desc |= N_REF_TO_WEAK;
 
3504                 fReferencesWeakImports = true;
 
3506         // set weak_import attribute
 
3507         if ( fWeakImportMap[atom] ) 
 
3509         entry->set_n_desc(desc);
 
3511         // set n_value, zero for import proxy and size for tentative definition
 
3512         entry->set_n_value(atom->getSize());
 
3516 template <typename A>
 
3517 void Writer<A>::setLocalNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry)
 
3520         const char* symbolName = this->symbolTableName(atom);
 
3522         if ( (fOptions.outputKind() == Options::kObjectFile) && !fOptions.keepLocalSymbol(symbolName) ) {
 
3523                 if ( stringsNeedLabelsInObjects() && (atom->getContentType() == ObjectFile::Atom::kCStringType) ) {
 
3524                         // don't use 'l' labels for x86_64 strings
 
3525                         // <rdar://problem/6605499> x86_64 obj-c runtime confused when static lib is stripped
 
3528                         sprintf(anonName, "l%u", fAnonNameIndex++);
 
3529                         symbolName = anonName;
 
3532         entry->set_n_strx(this->fStringsAtom->add(symbolName));
 
3535         uint8_t type = N_SECT;
 
3536         if ( atom->getDefinitionKind() == ObjectFile::Atom::kAbsoluteSymbol ) 
 
3538         if ( atom->getScope() == ObjectFile::Atom::scopeLinkageUnit )
 
3540         entry->set_n_type(type);
 
3542         // set n_sect (section number of implementation )
 
3543         uint8_t sectIndex = atom->getSection()->getIndex();
 
3544         if ( sectIndex == 0 ) {
 
3545                 // see <mach-o/ldsyms.h> synthesized lable for mach_header needs special section number...
 
3546                 if ( strcmp(atom->getSectionName(), "._mach_header") == 0 )
 
3549         entry->set_n_sect(sectIndex);
 
3553     if ( atom->dontDeadStrip() && (fOptions.outputKind() == Options::kObjectFile) )
 
3554         desc |= N_NO_DEAD_STRIP;
 
3555         if ( atom->getDefinitionKind() == ObjectFile::Atom::kWeakDefinition )
 
3557         if ( atom->isThumb() )
 
3558                 desc |= N_ARM_THUMB_DEF;
 
3559         entry->set_n_desc(desc);
 
3561         // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
 
3562         if ( atom->getDefinitionKind() == ObjectFile::Atom::kAbsoluteSymbol ) 
 
3563                 entry->set_n_value(atom->getSectionOffset());
 
3565                 entry->set_n_value(this->getAtomLoadAddress(atom));
 
3569 template <typename A>
 
3570 void Writer<A>::addLocalLabel(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* name)
 
3572         macho_nlist<P> entry;
 
3575         entry.set_n_strx(fStringsAtom->add(name));
 
3578         entry.set_n_type(N_SECT);
 
3580         // set n_sect (section number of implementation )
 
3581         entry.set_n_sect(atom.getSection()->getIndex());
 
3584         entry.set_n_desc(0);
 
3586         // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
 
3587         entry.set_n_value(this->getAtomLoadAddress(&atom) + offsetInAtom);
 
3590         fLocalExtraLabels.push_back(entry);
 
3595 template <typename A>
 
3596 void Writer<A>::addGlobalLabel(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* name)
 
3598         macho_nlist<P> entry;
 
3601         entry.set_n_strx(fStringsAtom->add(name));
 
3604         entry.set_n_type(N_SECT|N_EXT);
 
3606         // set n_sect (section number of implementation )
 
3607         entry.set_n_sect(atom.getSection()->getIndex());
 
3610         entry.set_n_desc(0);
 
3612         // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
 
3613         entry.set_n_value(this->getAtomLoadAddress(&atom) + offsetInAtom);
 
3616         fGlobalExtraLabels.push_back(entry);
 
3619 template <typename A>
 
3620 void Writer<A>::setNlistRange(std::vector<class ObjectFile::Atom*>& atoms, uint32_t startIndex, uint32_t count)
 
3622         macho_nlist<P>* entry = &fSymbolTable[startIndex];
 
3623         for (uint32_t i=0; i < count; ++i, ++entry) {
 
3624                 ObjectFile::Atom* atom = atoms[i];
 
3625                 if ( &atoms == &fExportedAtoms ) {
 
3626                         this->setExportNlist(atom, entry);
 
3628                 else if ( &atoms == &fImportedAtoms ) {
 
3629                         this->setImportNlist(atom, entry);
 
3632                         this->setLocalNlist(atom, entry);
 
3637 template <typename A>
 
3638 void Writer<A>::copyNlistRange(const std::vector<macho_nlist<P> >& entries, uint32_t startIndex)
 
3640         for ( typename std::vector<macho_nlist<P> >::const_iterator it = entries.begin(); it != entries.end(); ++it) 
 
3641                 fSymbolTable[startIndex++] = *it;
 
3645 template <typename A>
 
3646 struct NListNameSorter
 
3648         NListNameSorter(StringsLinkEditAtom<A>* pool) : fStringPool(pool) {}
 
3650      bool operator()(const macho_nlist<typename A::P>& left, const macho_nlist<typename A::P>& right)
 
3652           return (strcmp(fStringPool->stringForIndex(left.n_strx()), fStringPool->stringForIndex(right.n_strx())) < 0);
 
3655         StringsLinkEditAtom<A>*         fStringPool;
 
3659 template <typename A>
 
3660 void Writer<A>::buildSymbolTable()
 
3662         fSymbolTableStabsStartIndex             = 0;
 
3663         fSymbolTableStabsCount                  = fStabs->size();
 
3664         fSymbolTableLocalStartIndex             = fSymbolTableStabsStartIndex + fSymbolTableStabsCount;
 
3665         fSymbolTableLocalCount                  = fLocalSymbolAtoms.size() + fLocalExtraLabels.size();
 
3666         fSymbolTableExportStartIndex    = fSymbolTableLocalStartIndex + fSymbolTableLocalCount;
 
3667         fSymbolTableExportCount                 = fExportedAtoms.size() + fGlobalExtraLabels.size();
 
3668         fSymbolTableImportStartIndex    = fSymbolTableExportStartIndex + fSymbolTableExportCount;
 
3669         fSymbolTableImportCount                 = fImportedAtoms.size();
 
3671         // allocate symbol table
 
3672         fSymbolTableCount = fSymbolTableStabsCount + fSymbolTableLocalCount + fSymbolTableExportCount + fSymbolTableImportCount;
 
3673         fSymbolTable = new macho_nlist<P>[fSymbolTableCount];
 
3675         // fill in symbol table and string pool (do stabs last so strings are at end of pool)
 
3676         setNlistRange(fLocalSymbolAtoms, fSymbolTableLocalStartIndex,  fLocalSymbolAtoms.size());
 
3677         if ( fLocalExtraLabels.size() != 0 )
 
3678                 copyNlistRange(fLocalExtraLabels, fSymbolTableLocalStartIndex+fLocalSymbolAtoms.size());
 
3679         setNlistRange(fExportedAtoms,    fSymbolTableExportStartIndex, fExportedAtoms.size());
 
3680         if ( fGlobalExtraLabels.size() != 0 ) {
 
3681                 copyNlistRange(fGlobalExtraLabels, fSymbolTableExportStartIndex+fExportedAtoms.size());
 
3682                 // re-sort combined range
 
3683                 std::sort(  &fSymbolTable[fSymbolTableExportStartIndex], 
 
3684                                         &fSymbolTable[fSymbolTableExportStartIndex+fSymbolTableExportCount], 
 
3685                                         NListNameSorter<A>(fStringsAtom) );
 
3687         setNlistRange(fImportedAtoms,    fSymbolTableImportStartIndex, fSymbolTableImportCount);
 
3688         addStabs(fSymbolTableStabsStartIndex);
 
3690         // set up module table
 
3691         if ( fModuleInfoAtom != NULL )
 
3692                 fModuleInfoAtom->setName();
 
3694         // create atom to symbol index map
 
3697         for(std::vector<ObjectFile::Atom*>::iterator it=fImportedAtoms.begin(); it != fImportedAtoms.end(); ++it) {
 
3698                 fAtomToSymbolIndex[*it] = i + fSymbolTableImportStartIndex;
 
3703         for(std::vector<ObjectFile::Atom*>::iterator it=fLocalSymbolAtoms.begin(); it != fLocalSymbolAtoms.end(); ++it) {
 
3704                 fAtomToSymbolIndex[*it] = i + fSymbolTableLocalStartIndex;
 
3709         for(std::vector<ObjectFile::Atom*>::iterator it=fExportedAtoms.begin(); it != fExportedAtoms.end(); ++it) {
 
3710                 fAtomToSymbolIndex[*it] = i + fSymbolTableExportStartIndex;
 
3718 template <typename A>
 
3719 bool Writer<A>::shouldExport(const ObjectFile::Atom& atom) const
 
3721         switch ( atom.getSymbolTableInclusion() ) {
 
3722                 case ObjectFile::Atom::kSymbolTableNotIn:
 
3724                 case ObjectFile::Atom::kSymbolTableInAndNeverStrip:
 
3726                 case ObjectFile::Atom::kSymbolTableInAsAbsolute:
 
3727                 case ObjectFile::Atom::kSymbolTableIn:
 
3728                         switch ( atom.getScope() ) {
 
3729                                 case ObjectFile::Atom::scopeGlobal:
 
3731                                 case ObjectFile::Atom::scopeLinkageUnit:
 
3732                                         return ( (fOptions.outputKind() == Options::kObjectFile) && fOptions.keepPrivateExterns() );
 
3741 template <typename A>
 
3742 void Writer<A>::collectExportedAndImportedAndLocalAtoms()
 
3744         const int atomCount = fAllAtoms->size();
 
3745         // guess at sizes of each bucket to minimize re-allocations
 
3746         fImportedAtoms.reserve(100);
 
3747         fExportedAtoms.reserve(atomCount/2);
 
3748         fLocalSymbolAtoms.reserve(atomCount);
 
3750         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
3751                 std::vector<SectionInfo*>& sectionInfos = (*segit)->fSections;
 
3752                 for (std::vector<SectionInfo*>::iterator secit = sectionInfos.begin(); secit != sectionInfos.end(); ++secit) {
 
3753                         std::vector<ObjectFile::Atom*>& sectionAtoms = (*secit)->fAtoms;
 
3754                         for (std::vector<ObjectFile::Atom*>::iterator ait = sectionAtoms.begin(); ait != sectionAtoms.end(); ++ait) {
 
3755                                 ObjectFile::Atom* atom = *ait;
 
3756                                 // only named atoms go in symbol table
 
3757                                 if ( atom->getName() != NULL ) {
 
3758                                         // put atom into correct bucket: imports, exports, locals
 
3759                                         //fprintf(stderr, "collectExportedAndImportedAndLocalAtoms() name=%s\n", atom->getDisplayName());
 
3760                                         switch ( atom->getDefinitionKind() ) {
 
3761                                                 case ObjectFile::Atom::kExternalDefinition:
 
3762                                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
3763                                                         fImportedAtoms.push_back(atom);
 
3765                                                 case ObjectFile::Atom::kTentativeDefinition:
 
3766                                                         if ( (fOptions.outputKind() == Options::kObjectFile) && !fOptions.readerOptions().fMakeTentativeDefinitionsReal ) {
 
3767                                                                 fImportedAtoms.push_back(atom);
 
3771                                                 case ObjectFile::Atom::kWeakDefinition:
 
3772                                                         if ( stringsNeedLabelsInObjects() 
 
3773                                                                         && (fOptions.outputKind() == Options::kObjectFile)      
 
3774                                                                         && (atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableIn) 
 
3775                                                                         && (atom->getScope() == ObjectFile::Atom::scopeLinkageUnit) 
 
3776                                                                         && (atom->getContentType() == ObjectFile::Atom::kCStringType) ) {
 
3777                                                                 fLocalSymbolAtoms.push_back(atom);
 
3781                                                 case ObjectFile::Atom::kRegularDefinition:
 
3782                                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
3783                                                         if ( this->shouldExport(*atom) )
 
3784                                                                 fExportedAtoms.push_back(atom);
 
3785                                                         else if ( (atom->getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn)
 
3786                                                                 && ((fOptions.outputKind() == Options::kObjectFile) || fOptions.keepLocalSymbol(atom->getName())) )
 
3787                                                                 fLocalSymbolAtoms.push_back(atom);
 
3791                                 // when geneating a .o file, dtrace static probes become local labels
 
3792                                 if ( (fOptions.outputKind() == Options::kObjectFile) && !fOptions.readerOptions().fForStatic ) {
 
3793                                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
3794                                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
3795                                                 ObjectFile::Reference* ref = *rit;
 
3796                                                 if ( ref->getKind() == A::kDtraceProbe ) {
 
3797                                                         // dtrace probe points to be add back into generated .o file
 
3798                                                         this->addLocalLabel(*atom, ref->getFixUpOffset(), ref->getTargetName());
 
3802                                 // when linking kernel, old style dtrace static probes become global labels
 
3803                                 else if ( fOptions.readerOptions().fForStatic ) {
 
3804                                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
3805                                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
3806                                                 ObjectFile::Reference* ref = *rit;
 
3807                                                 if ( ref->getKind() == A::kDtraceProbe ) {
 
3808                                                         // dtrace probe points to be add back into generated .o file
 
3809                                                         this->addGlobalLabel(*atom, ref->getFixUpOffset(), ref->getTargetName());
 
3817         // sort exported atoms by name
 
3818         std::sort(fExportedAtoms.begin(), fExportedAtoms.end(), AtomByNameSorter());
 
3819         // sort imported atoms by name (not required by runtime, but helps make generated files binary diffable)
 
3820         std::sort(fImportedAtoms.begin(), fImportedAtoms.end(), AtomByNameSorter());
 
3824 template <typename A>
 
3825 uint64_t Writer<A>::valueForStab(const ObjectFile::Reader::Stab& stab)
 
3827         switch ( stab.type ) {
 
3829                         if ( (stab.string == NULL) || (strlen(stab.string) == 0) ) {
 
3830                                 // end of function N_FUN has size
 
3831                                 return stab.atom->getSize();
 
3834                                 // start of function N_FUN has address
 
3835                                 return getAtomLoadAddress(stab.atom);
 
3840                         if ( stab.atom == NULL )
 
3841                                 // some weird assembly files have slines not associated with a function
 
3844                                 // all these stab types need their value changed from an offset in the atom to an address
 
3845                                 return getAtomLoadAddress(stab.atom) + stab.value;
 
3849                         // all these need address of atom
 
3850                         return getAtomLoadAddress(stab.atom);;
 
3852                         return stab.atom->getSize();
 
3854                         if ( stab.atom == NULL ) {
 
3858                                 if ( (stab.string == NULL) || (strlen(stab.string) == 0) ) {
 
3859                                         // end of translation unit N_SO has address of end of last atom
 
3860                                         return getAtomLoadAddress(stab.atom) + stab.atom->getSize();
 
3863                                         // start of translation unit N_SO has address of end of first atom
 
3864                                         return getAtomLoadAddress(stab.atom);
 
3873 template <typename A>
 
3874 uint32_t Writer<A>::stringOffsetForStab(const ObjectFile::Reader::Stab& stab)
 
3876         switch (stab.type) {
 
3878                         if ( (stab.string == NULL) || stab.string[0] == '\0' ) {
 
3879                                 return this->fStringsAtom->emptyString();
 
3882                         // fall into uniquing case
 
3886                         return this->fStringsAtom->addUnique(stab.string);
 
3889                         if ( stab.string == NULL )
 
3891                         else if ( stab.string[0] == '\0' )
 
3892                                 return this->fStringsAtom->emptyString();
 
3894                                 return this->fStringsAtom->add(stab.string);
 
3899 template <typename A>
 
3900 uint8_t Writer<A>::sectionIndexForStab(const ObjectFile::Reader::Stab& stab)
 
3902         // in FUN stabs, n_sect field is 0 for start FUN and 1 for end FUN
 
3903         if ( stab.type == N_FUN )
 
3905         else if ( stab.atom != NULL ) 
 
3906                 return stab.atom->getSection()->getIndex();
 
3911 template <typename A>
 
3912 void Writer<A>::addStabs(uint32_t startIndex)
 
3914         macho_nlist<P>* entry = &fSymbolTable[startIndex];
 
3915         for(std::vector<ObjectFile::Reader::Stab>::iterator it = fStabs->begin(); it != fStabs->end(); ++it, ++entry) {
 
3916                 const ObjectFile::Reader::Stab& stab = *it;
 
3917                 entry->set_n_type(stab.type);
 
3918                 entry->set_n_sect(sectionIndexForStab(stab));
 
3919                 entry->set_n_desc(stab.desc);
 
3920                 entry->set_n_value(valueForStab(stab));
 
3921                 entry->set_n_strx(stringOffsetForStab(stab));
 
3927 template <typename A>
 
3928 uint32_t Writer<A>::symbolIndex(ObjectFile::Atom& atom)
 
3930         std::map<ObjectFile::Atom*, uint32_t>::iterator pos = fAtomToSymbolIndex.find(&atom);
 
3931         if ( pos != fAtomToSymbolIndex.end() )
 
3933         throwf("atom not found in symbolIndex(%s) for %s", atom.getDisplayName(), atom.getFile()->getPath());
 
3938 bool Writer<x86_64>::makesExternalRelocatableReference(ObjectFile::Atom& target) const
 
3940         switch ( target.getSymbolTableInclusion() )      {
 
3941                 case ObjectFile::Atom::kSymbolTableNotIn:
 
3943                 case ObjectFile::Atom::kSymbolTableInAsAbsolute:
 
3944                 case ObjectFile::Atom::kSymbolTableIn:
 
3945                 case ObjectFile::Atom::kSymbolTableInAndNeverStrip:
 
3951 template <typename A>
 
3952 bool Writer<A>::makesExternalRelocatableReference(ObjectFile::Atom& target) const
 
3954         switch ( target.getDefinitionKind() ) {
 
3955                 case ObjectFile::Atom::kRegularDefinition:
 
3956                 case ObjectFile::Atom::kWeakDefinition:
 
3957                 case ObjectFile::Atom::kAbsoluteSymbol:
 
3959                 case ObjectFile::Atom::kTentativeDefinition:
 
3960                         if ( fOptions.readerOptions().fMakeTentativeDefinitionsReal )
 
3963                                 return (target.getScope() != ObjectFile::Atom::scopeTranslationUnit);
 
3964                 case ObjectFile::Atom::kExternalDefinition:
 
3965                 case ObjectFile::Atom::kExternalWeakDefinition:
 
3966                         return shouldExport(target);
 
3971 template <typename A>
 
3972 void Writer<A>::buildFixups()
 
3974         if ( fOptions.outputKind() == Options::kObjectFile ) {
 
3975                 this->buildObjectFileFixups();
 
3978                 if ( fOptions.keepRelocations() )
 
3979                         this->buildObjectFileFixups();
 
3980                 this->buildExecutableFixups();
 
3985 uint32_t Writer<x86_64>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 
3987         ObjectFile::Atom& target = ref->getTarget();
 
3988         bool external = this->makesExternalRelocatableReference(target);
 
3989         uint32_t symbolIndex = external ? this->symbolIndex(target) : target.getSection()->getIndex();
 
3990         uint32_t address = atom->getSectionOffset()+ref->getFixUpOffset();
 
3991         macho_relocation_info<P> reloc1;
 
3992         macho_relocation_info<P> reloc2;
 
3993         x86_64::ReferenceKinds kind = (x86_64::ReferenceKinds)ref->getKind();
 
3996                 case x86_64::kNoFixUp:
 
3997                 case x86_64::kGOTNoFixUp:
 
3998                 case x86_64::kFollowOn:
 
3999                 case x86_64::kGroupSubordinate:
 
4002                 case x86_64::kPointer:
 
4003                 case x86_64::kPointerWeakImport:
 
4004                         reloc1.set_r_address(address);
 
4005                         reloc1.set_r_symbolnum(symbolIndex);
 
4006                         reloc1.set_r_pcrel(false);
 
4007                         reloc1.set_r_length(3);
 
4008                         reloc1.set_r_extern(external);
 
4009                         reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
 
4010                         fSectionRelocs.push_back(reloc1);
 
4013                 case x86_64::kPointer32:
 
4014                         reloc1.set_r_address(address);
 
4015                         reloc1.set_r_symbolnum(symbolIndex);
 
4016                         reloc1.set_r_pcrel(false);
 
4017                         reloc1.set_r_length(2);
 
4018                         reloc1.set_r_extern(external);
 
4019                         reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
 
4020                         fSectionRelocs.push_back(reloc1);
 
4023                 case x86_64::kPointerDiff32:
 
4024                 case x86_64::kPointerDiff:      
 
4026                         ObjectFile::Atom& fromTarget = ref->getFromTarget();
 
4027                         bool fromExternal = (fromTarget.getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn);
 
4028                         uint32_t fromSymbolIndex = fromExternal ? this->symbolIndex(fromTarget) : fromTarget.getSection()->getIndex();
 
4029                         reloc1.set_r_address(address);
 
4030                         reloc1.set_r_symbolnum(symbolIndex);
 
4031                         reloc1.set_r_pcrel(false);
 
4032                         reloc1.set_r_length(kind==x86_64::kPointerDiff32 ? 2 : 3);
 
4033                         reloc1.set_r_extern(external);
 
4034                         reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
 
4035                         reloc2.set_r_address(address);
 
4036                         reloc2.set_r_symbolnum(fromSymbolIndex);
 
4037                         reloc2.set_r_pcrel(false);
 
4038                         reloc2.set_r_length(kind==x86_64::kPointerDiff32 ? 2 : 3);
 
4039                         reloc2.set_r_extern(fromExternal);
 
4040                         reloc2.set_r_type(X86_64_RELOC_SUBTRACTOR);
 
4041                         fSectionRelocs.push_back(reloc1);
 
4042                         fSectionRelocs.push_back(reloc2);
 
4046                 case x86_64::kBranchPCRel32:
 
4047                 case x86_64::kBranchPCRel32WeakImport:
 
4048                 case x86_64::kDtraceProbeSite:
 
4049                 case x86_64::kDtraceIsEnabledSite:
 
4050                         reloc1.set_r_address(address);
 
4051                         reloc1.set_r_symbolnum(symbolIndex);
 
4052                         reloc1.set_r_pcrel(true);
 
4053                         reloc1.set_r_length(2);
 
4054                         reloc1.set_r_extern(external);
 
4055                         reloc1.set_r_type(X86_64_RELOC_BRANCH);
 
4056                         fSectionRelocs.push_back(reloc1);
 
4059                 case x86_64::kPCRel32:
 
4060                         reloc1.set_r_address(address);
 
4061                         reloc1.set_r_symbolnum(symbolIndex);
 
4062                         reloc1.set_r_pcrel(true);
 
4063                         reloc1.set_r_length(2);
 
4064                         reloc1.set_r_extern(external);
 
4065                         reloc1.set_r_type(X86_64_RELOC_SIGNED);
 
4066                         fSectionRelocs.push_back(reloc1);
 
4069                 case x86_64::kPCRel32_1:
 
4070                         reloc1.set_r_address(address);
 
4071                         reloc1.set_r_symbolnum(symbolIndex);
 
4072                         reloc1.set_r_pcrel(true);
 
4073                         reloc1.set_r_length(2);
 
4074                         reloc1.set_r_extern(external);
 
4075                         reloc1.set_r_type(X86_64_RELOC_SIGNED_1);
 
4076                         fSectionRelocs.push_back(reloc1);
 
4079                 case x86_64::kPCRel32_2:
 
4080                         reloc1.set_r_address(address);
 
4081                         reloc1.set_r_symbolnum(symbolIndex);
 
4082                         reloc1.set_r_pcrel(true);
 
4083                         reloc1.set_r_length(2);
 
4084                         reloc1.set_r_extern(external);
 
4085                         reloc1.set_r_type(X86_64_RELOC_SIGNED_2);
 
4086                         fSectionRelocs.push_back(reloc1);
 
4089                 case x86_64::kPCRel32_4:
 
4090                         reloc1.set_r_address(address);
 
4091                         reloc1.set_r_symbolnum(symbolIndex);
 
4092                         reloc1.set_r_pcrel(true);
 
4093                         reloc1.set_r_length(2);
 
4094                         reloc1.set_r_extern(external);
 
4095                         reloc1.set_r_type(X86_64_RELOC_SIGNED_4);
 
4096                         fSectionRelocs.push_back(reloc1);
 
4099                 case x86_64::kBranchPCRel8:
 
4100                         reloc1.set_r_address(address);
 
4101                         reloc1.set_r_symbolnum(symbolIndex);
 
4102                         reloc1.set_r_pcrel(true);
 
4103                         reloc1.set_r_length(0);
 
4104                         reloc1.set_r_extern(external);
 
4105                         reloc1.set_r_type(X86_64_RELOC_BRANCH);
 
4106                         fSectionRelocs.push_back(reloc1);
 
4109                 case x86_64::kPCRel32GOT:
 
4110                 case x86_64::kPCRel32GOTWeakImport:
 
4111                         reloc1.set_r_address(address);
 
4112                         reloc1.set_r_symbolnum(symbolIndex);
 
4113                         reloc1.set_r_pcrel(true);
 
4114                         reloc1.set_r_length(2);
 
4115                         reloc1.set_r_extern(external);
 
4116                         reloc1.set_r_type(X86_64_RELOC_GOT);
 
4117                         fSectionRelocs.push_back(reloc1);
 
4120                 case x86_64::kPCRel32GOTLoad:
 
4121                 case x86_64::kPCRel32GOTLoadWeakImport:
 
4122                         reloc1.set_r_address(address);
 
4123                         reloc1.set_r_symbolnum(symbolIndex);
 
4124                         reloc1.set_r_pcrel(true);
 
4125                         reloc1.set_r_length(2);
 
4126                         reloc1.set_r_extern(external);
 
4127                         reloc1.set_r_type(X86_64_RELOC_GOT_LOAD);
 
4128                         fSectionRelocs.push_back(reloc1);
 
4131                 case x86_64::kPointerDiff24:
 
4132                         throw "internal linker error, kPointerDiff24 can't be encoded into object files";
 
4134                 case x86_64::kImageOffset32:
 
4135                         throw "internal linker error, kImageOffset32 can't be encoded into object files";
 
4137                 case x86_64::kSectionOffset24:
 
4138                         throw "internal linker error, kSectionOffset24 can't be encoded into object files";
 
4140                 case x86_64::kDtraceTypeReference:
 
4141                 case x86_64::kDtraceProbe:
 
4142                         // generates no relocs
 
4150 uint32_t Writer<x86>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 
4152         ObjectFile::Atom& target = ref->getTarget();
 
4153         bool isExtern = this->makesExternalRelocatableReference(target);
 
4154         uint32_t symbolIndex = 0;
 
4156                 symbolIndex = this->symbolIndex(target);
 
4157         uint32_t sectionNum = target.getSection()->getIndex();
 
4158         uint32_t address = atom->getSectionOffset()+ref->getFixUpOffset();
 
4159         macho_relocation_info<P> reloc1;
 
4160         macho_relocation_info<P> reloc2;
 
4161         macho_scattered_relocation_info<P>* sreloc1 = (macho_scattered_relocation_info<P>*)&reloc1;
 
4162         macho_scattered_relocation_info<P>* sreloc2 = (macho_scattered_relocation_info<P>*)&reloc2;
 
4163         x86::ReferenceKinds kind = (x86::ReferenceKinds)ref->getKind();
 
4165         if ( !isExtern && (sectionNum == 0) && (target.getDefinitionKind() != ObjectFile::Atom::kAbsoluteSymbol) )
 
4166                 warning("section index == 0 for %s (kind=%d, scope=%d, inclusion=%d) in %s",
 
4167                  target.getDisplayName(), target.getDefinitionKind(), target.getScope(), target.getSymbolTableInclusion(), target.getFile()->getPath());
 
4172                 case x86::kFollowOn:
 
4173                 case x86::kGroupSubordinate:
 
4177                 case x86::kPointerWeakImport:
 
4178                 case x86::kAbsolute32:
 
4179                         if ( !isExtern && (ref->getTargetOffset() != 0) ) {
 
4180                                 // use scattered reloc is target offset is non-zero
 
4181                                 sreloc1->set_r_scattered(true);
 
4182                                 sreloc1->set_r_pcrel(false);
 
4183                                 sreloc1->set_r_length(2);
 
4184                                 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
 
4185                                 sreloc1->set_r_address(address);
 
4186                                 sreloc1->set_r_value(target.getAddress());
 
4189                                 reloc1.set_r_address(address);
 
4190                                 reloc1.set_r_symbolnum(isExtern ? symbolIndex : sectionNum);
 
4191                                 reloc1.set_r_pcrel(false);
 
4192                                 reloc1.set_r_length(2);
 
4193                                 reloc1.set_r_extern(isExtern);
 
4194                                 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
 
4196                         fSectionRelocs.push_back(reloc1);
 
4199                 case x86::kPointerDiff16:
 
4200                 case x86::kPointerDiff:
 
4202                                 //pint_t fromAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
 
4203                                 //fprintf(stderr, "addObjectRelocs(): refFromTarget=%s, refTarget=%s, refFromTargetAddr=0x%llX, refFromTargetOffset=0x%llX\n",
 
4204                                 //                      ref->getFromTarget().getDisplayName(), ref->getTarget().getDisplayName(), 
 
4205                                 //                      ref->getFromTarget().getAddress(), ref->getFromTargetOffset());
 
4206                                 sreloc1->set_r_scattered(true);
 
4207                                 sreloc1->set_r_pcrel(false);
 
4208                                 sreloc1->set_r_length( (kind==x86::kPointerDiff) ? 2 : 1 );
 
4209                                 if ( ref->getTarget().getScope() == ObjectFile::Atom::scopeTranslationUnit )
 
4210                                         sreloc1->set_r_type(GENERIC_RELOC_LOCAL_SECTDIFF);
 
4212                                         sreloc1->set_r_type(GENERIC_RELOC_SECTDIFF);
 
4213                                 sreloc1->set_r_address(address);
 
4214                                 sreloc1->set_r_value(target.getAddress());
 
4216                                 sreloc2->set_r_scattered(true);
 
4217                                 sreloc2->set_r_pcrel(false);
 
4218                                 sreloc2->set_r_length( (kind==x86::kPointerDiff) ? 2 : 1 );
 
4219                                 sreloc2->set_r_type(GENERIC_RELOC_PAIR);
 
4220                                 sreloc2->set_r_address(0);
 
4221                                 if ( &ref->getFromTarget() == atom )
 
4222                                         sreloc2->set_r_value(ref->getFromTarget().getAddress()+ref->getFromTargetOffset());
 
4224                                         sreloc2->set_r_value(ref->getFromTarget().getAddress());
 
4225                                 fSectionRelocs.push_back(reloc2);
 
4226                                 fSectionRelocs.push_back(reloc1);
 
4230                 case x86::kPCRel32WeakImport:
 
4234                 case x86::kDtraceProbeSite:
 
4235                 case x86::kDtraceIsEnabledSite:
 
4236                         if ( !isExtern && (ref->getTargetOffset() != 0) ) {
 
4237                                 // use scattered reloc is target offset is non-zero
 
4238                                 sreloc1->set_r_scattered(true);
 
4239                                 sreloc1->set_r_pcrel(true);
 
4240                                 sreloc1->set_r_length( (kind==x86::kPCRel8) ? 0 : ((kind==x86::kPCRel16) ? 1 : 2) );
 
4241                                 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
 
4242                                 sreloc1->set_r_address(address);
 
4243                                 sreloc1->set_r_value(target.getAddress());
 
4246                                 reloc1.set_r_address(address);
 
4247                                 reloc1.set_r_symbolnum(isExtern ? symbolIndex : sectionNum);
 
4248                                 reloc1.set_r_pcrel(true);
 
4249                                 reloc1.set_r_length( (kind==x86::kPCRel8) ? 0 : ((kind==x86::kPCRel16) ? 1 : 2) );
 
4250                                 reloc1.set_r_extern(isExtern);
 
4251                                 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
 
4253                         fSectionRelocs.push_back(reloc1);
 
4256                 case x86::kPointerDiff24:
 
4257                         throw "internal linker error, kPointerDiff24 can't be encoded into object files";
 
4259                 case x86::kImageOffset32:
 
4260                         throw "internal linker error, kImageOffset32 can't be encoded into object files";
 
4262                 case x86::kSectionOffset24:
 
4263                         throw "internal linker error, kSectionOffset24 can't be encoded into object files";
 
4265                 case x86::kDtraceTypeReference:
 
4266                 case x86::kDtraceProbe:
 
4267                         // generates no relocs
 
4275 uint32_t Writer<arm>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 
4277         ObjectFile::Atom& target = ref->getTarget();
 
4278         bool isExtern = this->makesExternalRelocatableReference(target);
 
4279         uint32_t symbolIndex = 0;
 
4281                 symbolIndex = this->symbolIndex(target);
 
4282         uint32_t sectionNum = target.getSection()->getIndex();
 
4283         uint32_t address = atom->getSectionOffset()+ref->getFixUpOffset();
 
4284         macho_relocation_info<P> reloc1;
 
4285         macho_relocation_info<P> reloc2;
 
4286         macho_scattered_relocation_info<P>* sreloc1 = (macho_scattered_relocation_info<P>*)&reloc1;
 
4287         macho_scattered_relocation_info<P>* sreloc2 = (macho_scattered_relocation_info<P>*)&reloc2;
 
4288         arm::ReferenceKinds kind = (arm::ReferenceKinds)ref->getKind();
 
4290         if ( !isExtern && (sectionNum == 0) && (target.getDefinitionKind() != ObjectFile::Atom::kAbsoluteSymbol) )
 
4291                 warning("section index == 0 for %s (kind=%d, scope=%d, inclusion=%d) in %s",
 
4292                  target.getDisplayName(), target.getDefinitionKind(), target.getScope(), target.getSymbolTableInclusion(), target.getFile()->getPath());
 
4297                 case arm::kFollowOn:
 
4298                 case arm::kGroupSubordinate:
 
4302                 case arm::kReadOnlyPointer:
 
4303                 case arm::kPointerWeakImport:
 
4304                         if ( !isExtern && (ref->getTargetOffset() != 0) ) {
 
4305                                 // use scattered reloc is target offset is non-zero
 
4306                                 sreloc1->set_r_scattered(true);
 
4307                                 sreloc1->set_r_pcrel(false);
 
4308                                 sreloc1->set_r_length(2);
 
4309                                 sreloc1->set_r_type(ARM_RELOC_VANILLA);
 
4310                                 sreloc1->set_r_address(address);
 
4311                                 sreloc1->set_r_value(target.getAddress());
 
4314                                 reloc1.set_r_address(address);
 
4315                                 reloc1.set_r_symbolnum(isExtern ? symbolIndex : sectionNum);
 
4316                                 reloc1.set_r_pcrel(false);
 
4317                                 reloc1.set_r_length(2);
 
4318                                 reloc1.set_r_extern(isExtern);
 
4319                                 reloc1.set_r_type(ARM_RELOC_VANILLA);
 
4321                         fSectionRelocs.push_back(reloc1);
 
4324                 case arm::kPointerDiff:
 
4326                                 sreloc1->set_r_scattered(true);
 
4327                                 sreloc1->set_r_pcrel(false);
 
4328                                 sreloc1->set_r_length(2);
 
4329                                 if ( ref->getTarget().getScope() == ObjectFile::Atom::scopeTranslationUnit )
 
4330                                         sreloc1->set_r_type(ARM_RELOC_LOCAL_SECTDIFF);
 
4332                                         sreloc1->set_r_type(ARM_RELOC_SECTDIFF);
 
4333                                 sreloc1->set_r_address(address);
 
4334                                 sreloc1->set_r_value(target.getAddress());
 
4335                                 sreloc2->set_r_scattered(true);
 
4336                                 sreloc2->set_r_pcrel(false);
 
4337                                 sreloc2->set_r_length(2);
 
4338                                 sreloc2->set_r_type(ARM_RELOC_PAIR);
 
4339                                 sreloc2->set_r_address(0);
 
4340                                 if ( &ref->getFromTarget() == atom )
 
4341                                         sreloc2->set_r_value(ref->getFromTarget().getAddress()+ref->getFromTargetOffset());
 
4343                                         sreloc2->set_r_value(ref->getFromTarget().getAddress());
 
4344                                 fSectionRelocs.push_back(reloc2);
 
4345                                 fSectionRelocs.push_back(reloc1);
 
4349                 case arm::kBranch24WeakImport:
 
4350                 case arm::kBranch24:
 
4351                 case arm::kDtraceProbeSite:
 
4352                 case arm::kDtraceIsEnabledSite:
 
4353                         if ( !isExtern && (ref->getTargetOffset() != 0) ) {
 
4354                                 // use scattered reloc is target offset is non-zero
 
4355                                 sreloc1->set_r_scattered(true);
 
4356                                 sreloc1->set_r_pcrel(true);
 
4357                                 sreloc1->set_r_length(2);
 
4358                                 sreloc1->set_r_type(ARM_RELOC_BR24);
 
4359                                 sreloc1->set_r_address(address);
 
4360                                 sreloc1->set_r_value(target.getAddress());
 
4363                                 reloc1.set_r_address(address);
 
4364                                 reloc1.set_r_symbolnum(isExtern ? symbolIndex : sectionNum);
 
4365                                 reloc1.set_r_pcrel(true);
 
4366                                 reloc1.set_r_length(2);
 
4367                                 reloc1.set_r_extern(isExtern);
 
4368                                 reloc1.set_r_type(ARM_RELOC_BR24);
 
4370                         fSectionRelocs.push_back(reloc1);
 
4373                 case arm::kThumbBranch22WeakImport:
 
4374                 case arm::kThumbBranch22:
 
4375                         if ( !isExtern && (ref->getTargetOffset() != 0) ) {
 
4376                                 // use scattered reloc if target offset is non-zero
 
4377                                 sreloc1->set_r_scattered(true);
 
4378                                 sreloc1->set_r_pcrel(true);
 
4379                                 sreloc1->set_r_length(2);
 
4380                                 sreloc1->set_r_type(ARM_THUMB_RELOC_BR22);
 
4381                                 sreloc1->set_r_address(address);
 
4382                                 sreloc1->set_r_value(target.getAddress());
 
4385                                 reloc1.set_r_address(address);
 
4386                                 reloc1.set_r_symbolnum(isExtern ? symbolIndex : sectionNum);
 
4387                                 reloc1.set_r_pcrel(true);
 
4388                                 reloc1.set_r_length(2);
 
4389                                 reloc1.set_r_extern(isExtern);
 
4390                                 reloc1.set_r_type(ARM_THUMB_RELOC_BR22);
 
4392                         fSectionRelocs.push_back(reloc1);
 
4395                 case arm::kPointerDiff12:
 
4396                         throw "internal error.  no reloc for 12-bit pointer diffs";
 
4398                 case arm::kDtraceTypeReference:
 
4399                 case arm::kDtraceProbe:
 
4400                         // generates no relocs
 
4407 template <> uint64_t    Writer<ppc>::maxAddress() { return 0xFFFFFFFFULL; }
 
4408 template <> uint64_t  Writer<ppc64>::maxAddress() { return 0xFFFFFFFFFFFFFFFFULL; }
 
4409 template <> uint64_t    Writer<x86>::maxAddress() { return 0xFFFFFFFFULL; }
 
4410 template <> uint64_t Writer<x86_64>::maxAddress() { return 0xFFFFFFFFFFFFFFFFULL; }
 
4411 template <> uint64_t    Writer<arm>::maxAddress() { return 0xFFFFFFFFULL; }
 
4414 uint8_t Writer<ppc>::getRelocPointerSize()
 
4420 uint8_t Writer<ppc64>::getRelocPointerSize()
 
4426 uint32_t Writer<ppc>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 
4428         return addObjectRelocs_powerpc(atom, ref);
 
4432 uint32_t Writer<ppc64>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 
4434         return addObjectRelocs_powerpc(atom, ref);
 
4438 // addObjectRelocs<ppc> and addObjectRelocs<ppc64> are almost exactly the same, so
 
4439 // they use a common addObjectRelocs_powerpc() method.
 
4441 template <typename A>
 
4442 uint32_t Writer<A>::addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 
4444         ObjectFile::Atom& target = ref->getTarget();
 
4445         bool isExtern = this->makesExternalRelocatableReference(target);        
 
4446         uint32_t symbolIndex = 0;
 
4448                 symbolIndex = this->symbolIndex(target);
 
4449         uint32_t sectionNum = target.getSection()->getIndex();
 
4450         uint32_t address = atom->getSectionOffset()+ref->getFixUpOffset();
 
4451         macho_relocation_info<P> reloc1;
 
4452         macho_relocation_info<P> reloc2;
 
4453         macho_scattered_relocation_info<P>* sreloc1 = (macho_scattered_relocation_info<P>*)&reloc1;
 
4454         macho_scattered_relocation_info<P>* sreloc2 = (macho_scattered_relocation_info<P>*)&reloc2;
 
4455         typename A::ReferenceKinds kind = (typename A::ReferenceKinds)ref->getKind();
 
4460                 case A::kGroupSubordinate:
 
4464                 case A::kPointerWeakImport:
 
4465                         if ( !isExtern && (ref->getTargetOffset() >= target.getSize()) ) {
 
4466                                 // use scattered reloc is target offset is outside target
 
4467                                 sreloc1->set_r_scattered(true);
 
4468                                 sreloc1->set_r_pcrel(false);
 
4469                                 sreloc1->set_r_length(getRelocPointerSize());
 
4470                                 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
 
4471                                 sreloc1->set_r_address(address);
 
4472                                 sreloc1->set_r_value(target.getAddress());
 
4475                                 reloc1.set_r_address(address);
 
4477                                         reloc1.set_r_symbolnum(symbolIndex);
 
4479                                         reloc1.set_r_symbolnum(sectionNum);
 
4480                                 reloc1.set_r_pcrel(false);
 
4481                                 reloc1.set_r_length(getRelocPointerSize());
 
4482                                 reloc1.set_r_extern(isExtern);
 
4483                                 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
 
4485                         fSectionRelocs.push_back(reloc1);
 
4488                 case A::kPointerDiff16:
 
4489                 case A::kPointerDiff32:
 
4490                 case A::kPointerDiff64:
 
4492                                 sreloc1->set_r_scattered(true);
 
4493                                 sreloc1->set_r_pcrel(false);
 
4494                                 sreloc1->set_r_length( (kind == A::kPointerDiff32) ? 2 : ((kind == A::kPointerDiff64) ? 3 : 1));
 
4495                                 if ( ref->getTarget().getScope() == ObjectFile::Atom::scopeTranslationUnit )
 
4496                                         sreloc1->set_r_type(PPC_RELOC_LOCAL_SECTDIFF);
 
4498                                         sreloc1->set_r_type(PPC_RELOC_SECTDIFF);
 
4499                                 sreloc1->set_r_address(address);
 
4500                                 sreloc1->set_r_value(target.getAddress()); 
 
4501                                 sreloc2->set_r_scattered(true);
 
4502                                 sreloc2->set_r_pcrel(false);
 
4503                                 sreloc2->set_r_length(sreloc1->r_length());
 
4504                                 sreloc2->set_r_type(PPC_RELOC_PAIR);
 
4505                                 sreloc2->set_r_address(0);
 
4506                                 sreloc2->set_r_value(ref->getFromTarget().getAddress()+ref->getFromTargetOffset()); 
 
4507                                 fSectionRelocs.push_back(reloc2);
 
4508                                 fSectionRelocs.push_back(reloc1);
 
4512                 case A::kBranch24WeakImport:
 
4514                 case A::kDtraceProbeSite:
 
4515                 case A::kDtraceIsEnabledSite:
 
4516                         if ( (ref->getTargetOffset() == 0) || isExtern ) {
 
4517                                 reloc1.set_r_address(address);
 
4519                                         reloc1.set_r_symbolnum(symbolIndex);
 
4521                                         reloc1.set_r_symbolnum(sectionNum);
 
4522                                 reloc1.set_r_pcrel(true);
 
4523                                 reloc1.set_r_length(2);
 
4524                                 reloc1.set_r_type(PPC_RELOC_BR24);
 
4525                                 reloc1.set_r_extern(isExtern);
 
4528                                 sreloc1->set_r_scattered(true);
 
4529                                 sreloc1->set_r_pcrel(true);
 
4530                                 sreloc1->set_r_length(2);
 
4531                                 sreloc1->set_r_type(PPC_RELOC_BR24);
 
4532                                 sreloc1->set_r_address(address);
 
4533                                 sreloc1->set_r_value(target.getAddress());
 
4535                         fSectionRelocs.push_back(reloc1);
 
4539                         if ( (ref->getTargetOffset() == 0) || isExtern ) {
 
4540                                 reloc1.set_r_address(address);
 
4542                                         reloc1.set_r_symbolnum(symbolIndex);
 
4544                                         reloc1.set_r_symbolnum(sectionNum);
 
4545                                 reloc1.set_r_pcrel(true);
 
4546                                 reloc1.set_r_length(2);
 
4547                                 reloc1.set_r_type(PPC_RELOC_BR14);
 
4548                                 reloc1.set_r_extern(isExtern);
 
4551                                 sreloc1->set_r_scattered(true);
 
4552                                 sreloc1->set_r_pcrel(true);
 
4553                                 sreloc1->set_r_length(2);
 
4554                                 sreloc1->set_r_type(PPC_RELOC_BR14);
 
4555                                 sreloc1->set_r_address(address);
 
4556                                 sreloc1->set_r_value(target.getAddress());
 
4558                         fSectionRelocs.push_back(reloc1);
 
4561                 case A::kPICBaseLow16:
 
4562                 case A::kPICBaseLow14:
 
4564                                 pint_t fromAddr = atom->getAddress() + ref->getFromTargetOffset();
 
4565                                 pint_t toAddr = target.getAddress() + ref->getTargetOffset();
 
4566                                 sreloc1->set_r_scattered(true);
 
4567                                 sreloc1->set_r_pcrel(false);
 
4568                                 sreloc1->set_r_length(2);
 
4569                                 sreloc1->set_r_type(kind == A::kPICBaseLow16 ? PPC_RELOC_LO16_SECTDIFF : PPC_RELOC_LO14_SECTDIFF);
 
4570                                 sreloc1->set_r_address(address);
 
4571                                 sreloc1->set_r_value(target.getAddress());
 
4572                                 sreloc2->set_r_scattered(true);
 
4573                                 sreloc2->set_r_pcrel(false);
 
4574                                 sreloc2->set_r_length(2);
 
4575                                 sreloc2->set_r_type(PPC_RELOC_PAIR);
 
4576                                 sreloc2->set_r_address(((toAddr-fromAddr) >> 16) & 0xFFFF);
 
4577                                 sreloc2->set_r_value(fromAddr);
 
4578                                 fSectionRelocs.push_back(reloc2);
 
4579                                 fSectionRelocs.push_back(reloc1);
 
4583                 case A::kPICBaseHigh16:
 
4585                                 pint_t fromAddr = atom->getAddress() + ref->getFromTargetOffset();
 
4586                                 pint_t toAddr = target.getAddress() + ref->getTargetOffset();
 
4587                                 sreloc1->set_r_scattered(true);
 
4588                                 sreloc1->set_r_pcrel(false);
 
4589                                 sreloc1->set_r_length(2);
 
4590                                 sreloc1->set_r_type(PPC_RELOC_HA16_SECTDIFF);
 
4591                                 sreloc1->set_r_address(address);
 
4592                                 sreloc1->set_r_value(target.getAddress());
 
4593                                 sreloc2->set_r_scattered(true);
 
4594                                 sreloc2->set_r_pcrel(false);
 
4595                                 sreloc2->set_r_length(2);
 
4596                                 sreloc2->set_r_type(PPC_RELOC_PAIR);
 
4597                                 sreloc2->set_r_address((toAddr-fromAddr) & 0xFFFF);
 
4598                                 sreloc2->set_r_value(fromAddr);
 
4599                                 fSectionRelocs.push_back(reloc2);
 
4600                                 fSectionRelocs.push_back(reloc1);
 
4607                                 pint_t toAddr = target.getAddress() + ref->getTargetOffset();
 
4608                                 if ( (ref->getTargetOffset() == 0) || isExtern ) {
 
4609                                         reloc1.set_r_address(address);
 
4611                                                 reloc1.set_r_symbolnum(symbolIndex);
 
4613                                                 reloc1.set_r_symbolnum(sectionNum);
 
4614                                         reloc1.set_r_pcrel(false);
 
4615                                         reloc1.set_r_length(2);
 
4616                                         reloc1.set_r_extern(isExtern);
 
4617                                         reloc1.set_r_type(kind==A::kAbsLow16 ? PPC_RELOC_LO16 : PPC_RELOC_LO14);
 
4620                                         sreloc1->set_r_scattered(true);
 
4621                                         sreloc1->set_r_pcrel(false);
 
4622                                         sreloc1->set_r_length(2);
 
4623                                         sreloc1->set_r_type(kind==A::kAbsLow16 ? PPC_RELOC_LO16 : PPC_RELOC_LO14);
 
4624                                         sreloc1->set_r_address(address);
 
4625                                         sreloc1->set_r_value(target.getAddress());
 
4628                                         reloc2.set_r_address(ref->getTargetOffset() >> 16);
 
4630                                         reloc2.set_r_address(toAddr >> 16);
 
4631                                 reloc2.set_r_symbolnum(0);
 
4632                                 reloc2.set_r_pcrel(false);
 
4633                                 reloc2.set_r_length(2);
 
4634                                 reloc2.set_r_extern(false);
 
4635                                 reloc2.set_r_type(PPC_RELOC_PAIR);
 
4636                                 fSectionRelocs.push_back(reloc2);
 
4637                                 fSectionRelocs.push_back(reloc1);
 
4643                                 pint_t toAddr = target.getAddress() + ref->getTargetOffset();
 
4644                                 if ( (ref->getTargetOffset() == 0) || isExtern ) {
 
4645                                         reloc1.set_r_address(address);
 
4647                                                 reloc1.set_r_symbolnum(symbolIndex);
 
4649                                                 reloc1.set_r_symbolnum(sectionNum);
 
4650                                         reloc1.set_r_pcrel(false);
 
4651                                         reloc1.set_r_length(2);
 
4652                                         reloc1.set_r_extern(isExtern);
 
4653                                         reloc1.set_r_type(PPC_RELOC_HI16);
 
4656                                         sreloc1->set_r_scattered(true);
 
4657                                         sreloc1->set_r_pcrel(false);
 
4658                                         sreloc1->set_r_length(2);
 
4659                                         sreloc1->set_r_type(PPC_RELOC_HI16);
 
4660                                         sreloc1->set_r_address(address);
 
4661                                         sreloc1->set_r_value(target.getAddress());
 
4664                                         reloc2.set_r_address(ref->getTargetOffset() & 0xFFFF);
 
4666                                         reloc2.set_r_address(toAddr & 0xFFFF);
 
4667                                 reloc2.set_r_symbolnum(0);
 
4668                                 reloc2.set_r_pcrel(false);
 
4669                                 reloc2.set_r_length(2);
 
4670                                 reloc2.set_r_extern(false);
 
4671                                 reloc2.set_r_type(PPC_RELOC_PAIR);
 
4672                                 fSectionRelocs.push_back(reloc2);
 
4673                                 fSectionRelocs.push_back(reloc1);
 
4677                 case A::kAbsHigh16AddLow:
 
4679                                 pint_t toAddr = target.getAddress() + ref->getTargetOffset();
 
4680                                 uint32_t overflow = 0;
 
4681                                 if ( (toAddr & 0x00008000) != 0 )
 
4683                                 if ( (ref->getTargetOffset() == 0) || isExtern ) {
 
4684                                         reloc1.set_r_address(address);
 
4686                                                 reloc1.set_r_symbolnum(symbolIndex);
 
4688                                                 reloc1.set_r_symbolnum(sectionNum);
 
4689                                         reloc1.set_r_pcrel(false);
 
4690                                         reloc1.set_r_length(2);
 
4691                                         reloc1.set_r_extern(isExtern);
 
4692                                         reloc1.set_r_type(PPC_RELOC_HA16);
 
4695                                         sreloc1->set_r_scattered(true);
 
4696                                         sreloc1->set_r_pcrel(false);
 
4697                                         sreloc1->set_r_length(2);
 
4698                                         sreloc1->set_r_type(PPC_RELOC_HA16);
 
4699                                         sreloc1->set_r_address(address);
 
4700                                         sreloc1->set_r_value(target.getAddress());
 
4703                                         reloc2.set_r_address(ref->getTargetOffset() & 0xFFFF);
 
4705                                         reloc2.set_r_address(toAddr & 0xFFFF);
 
4706                                 reloc2.set_r_symbolnum(0);
 
4707                                 reloc2.set_r_pcrel(false);
 
4708                                 reloc2.set_r_length(2);
 
4709                                 reloc2.set_r_extern(false);
 
4710                                 reloc2.set_r_type(PPC_RELOC_PAIR);
 
4711                                 fSectionRelocs.push_back(reloc2);
 
4712                                 fSectionRelocs.push_back(reloc1);
 
4716                 case A::kDtraceTypeReference:
 
4717                 case A::kDtraceProbe:
 
4718                         // generates no relocs
 
4727 // There are cases when an entry in the indirect symbol table is the magic value
 
4728 // INDIRECT_SYMBOL_LOCAL instead of being a symbol index.  When that happens
 
4729 // the content of the corresponding part of the __nl_symbol_pointer section
 
4730 // must also change. 
 
4732 template <typename A>
 
4733 bool Writer<A>::indirectSymbolInRelocatableIsLocal(const ObjectFile::Reference* ref) const
 
4735         // cannot use INDIRECT_SYMBOL_LOCAL to tentative definitions in object files
 
4736         // because tentative defs don't have addresses
 
4737         if ( ref->getTarget().getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition )
 
4740         // must use INDIRECT_SYMBOL_LOCAL if there is an addend 
 
4741         if ( ref->getTargetOffset() != 0 )
 
4744         // don't use INDIRECT_SYMBOL_LOCAL for external symbols
 
4745         return ! this->shouldExport(ref->getTarget());
 
4749 template <typename A>
 
4750 void Writer<A>::buildObjectFileFixups()
 
4752         uint32_t relocIndex = 0;
 
4753         std::vector<SegmentInfo*>& segmentInfos = fSegmentInfos;
 
4754         const int segCount = segmentInfos.size();
 
4755         for(int i=0; i < segCount; ++i) {
 
4756                 SegmentInfo* curSegment = segmentInfos[i];
 
4757                 std::vector<SectionInfo*>& sectionInfos = curSegment->fSections;
 
4758                 const int sectionCount = sectionInfos.size();
 
4759                 for(int j=0; j < sectionCount; ++j) {
 
4760                         SectionInfo* curSection = sectionInfos[j];
 
4761                         //fprintf(stderr, "buildObjectFileFixups(): starting section %s\n", curSection->fSectionName);
 
4762                         std::vector<ObjectFile::Atom*>& sectionAtoms = curSection->fAtoms;
 
4763                         if ( ! curSection->fAllZeroFill ) {
 
4764                                 if ( curSection->fAllNonLazyPointers || curSection->fAllLazyPointers
 
4765                                                         || curSection->fAllLazyDylibPointers || curSection->fAllStubs )
 
4766                                         curSection->fIndirectSymbolOffset = fIndirectTableAtom->fTable.size();
 
4767                                 curSection->fRelocOffset = relocIndex;
 
4768                                 const int atomCount = sectionAtoms.size();
 
4769                                 for (int k=0; k < atomCount; ++k) {
 
4770                                         ObjectFile::Atom* atom = sectionAtoms[k];
 
4771                                         //fprintf(stderr, "buildObjectFileFixups(): atom %s has %lu references\n", atom->getDisplayName(), atom->getReferences().size());
 
4772                                         std::vector<ObjectFile::Reference*>& refs = atom->getReferences();
 
4773                                         const int refCount = refs.size();
 
4774                                         for (int l=0; l < refCount; ++l) {
 
4775                                                 ObjectFile::Reference* ref = refs[l];
 
4776                                                 if ( curSection->fAllNonLazyPointers || curSection->fAllLazyPointers 
 
4777                                                                                 || curSection->fAllLazyDylibPointers || curSection->fAllStubs ) {
 
4778                                                         uint32_t offsetInSection = atom->getSectionOffset();
 
4779                                                         uint32_t indexInSection = offsetInSection / atom->getSize();
 
4780                                                         uint32_t undefinedSymbolIndex;
 
4781                                                         if ( curSection->fAllStubs ) {
 
4782                                                                 ObjectFile::Atom& stubTarget =ref->getTarget();
 
4783                                                                 ObjectFile::Atom& stubTargetTarget = stubTarget.getReferences()[0]->getTarget();
 
4784                                                                 undefinedSymbolIndex = this->symbolIndex(stubTargetTarget);
 
4785                                                                 //fprintf(stderr, "stub %s ==> %s ==> %s ==> index:%u\n", atom->getDisplayName(), stubTarget.getDisplayName(), stubTargetTarget.getDisplayName(), undefinedSymbolIndex);
 
4787                                                         else if ( curSection->fAllNonLazyPointers) {
 
4788                                                                 // only use INDIRECT_SYMBOL_LOCAL in non-lazy-pointers for atoms that won't be in symbol table or have an addend
 
4789                                                                 if ( this->indirectSymbolInRelocatableIsLocal(ref) )
 
4790                                                                         undefinedSymbolIndex = INDIRECT_SYMBOL_LOCAL;
 
4792                                                                         undefinedSymbolIndex = this->symbolIndex(ref->getTarget());
 
4795                                                                 // should never get here, fAllLazyPointers not used in generated .o files
 
4796                                                                 undefinedSymbolIndex = INDIRECT_SYMBOL_LOCAL;
 
4798                                                         uint32_t indirectTableIndex = indexInSection + curSection->fIndirectSymbolOffset;
 
4799                                                         IndirectEntry entry = { indirectTableIndex, undefinedSymbolIndex };
 
4800                                                         //printf("fIndirectTableAtom->fTable.add(sectionIndex=%u, indirectTableIndex=%u => %u), size=%lld\n", indexInSection, indirectTableIndex, undefinedSymbolIndex, atom->getSize());
 
4801                                                         fIndirectTableAtom->fTable.push_back(entry);
 
4802                                                         if ( curSection->fAllLazyPointers ) {
 
4803                                                                 ObjectFile::Atom& target = ref->getTarget();
 
4804                                                                 ObjectFile::Atom& fromTarget = ref->getFromTarget();
 
4805                                                                 if ( &fromTarget == NULL ) {
 
4806                                                                         warning("lazy pointer %s missing initial binding", atom->getDisplayName());
 
4809                                                                         bool isExtern = ( ((target.getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
 
4810                                                                                 || (target.getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition))
 
4811                                                                                 && (target.getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn) );
 
4812                                                                         macho_relocation_info<P> reloc1;
 
4813                                                                         reloc1.set_r_address(atom->getSectionOffset());
 
4814                                                                         reloc1.set_r_symbolnum(isExtern ? this->symbolIndex(target) : target.getSection()->getIndex());
 
4815                                                                         reloc1.set_r_pcrel(false);
 
4816                                                                         reloc1.set_r_length();
 
4817                                                                         reloc1.set_r_extern(isExtern);
 
4818                                                                         reloc1.set_r_type(GENERIC_RELOC_VANILLA);
 
4819                                                                         fSectionRelocs.push_back(reloc1);
 
4823                                                         else if ( curSection->fAllStubs ) {
 
4824                                                                 relocIndex += this->addObjectRelocs(atom, ref);
 
4827                                                 else if ( (ref->getKind() != A::kNoFixUp) && (ref->getTargetBinding() != ObjectFile::Reference::kDontBind) ) {
 
4828                                                         relocIndex += this->addObjectRelocs(atom, ref);
 
4832                                 curSection->fRelocCount = relocIndex - curSection->fRelocOffset;
 
4837         // reverse the relocs
 
4838         std::reverse(fSectionRelocs.begin(), fSectionRelocs.end());
 
4840         // now reverse section reloc offsets
 
4841         for(int i=0; i < segCount; ++i) {
 
4842                 SegmentInfo* curSegment = segmentInfos[i];
 
4843                 std::vector<SectionInfo*>& sectionInfos = curSegment->fSections;
 
4844                 const int sectionCount = sectionInfos.size();
 
4845                 for(int j=0; j < sectionCount; ++j) {
 
4846                         SectionInfo* curSection = sectionInfos[j];
 
4847                         curSection->fRelocOffset = relocIndex - curSection->fRelocOffset - curSection->fRelocCount;
 
4855 uint64_t Writer<x86_64>::relocAddressInFinalLinkedImage(uint64_t address, const ObjectFile::Atom* atom)  const
 
4858         if ( fOptions.outputKind() == Options::kKextBundle ) {
 
4859                 // for x86_64 kext bundles, the r_address field in relocs 
 
4860                 // is the offset from the start address of the first segment
 
4861                 result = address - fSegmentInfos[0]->fBaseAddress;
 
4862                 if ( result > 0xFFFFFFFF ) {
 
4863                         throwf("kext bundle too large: address can't fit in 31-bit r_address field in %s from %s",
 
4864                                 atom->getDisplayName(), atom->getFile()->getPath());
 
4868                 // for x86_64, the r_address field in relocs for final linked images 
 
4869                 // is the offset from the start address of the first writable segment
 
4870                 result = address - fFirstWritableSegment->fBaseAddress;
 
4871                 if ( result > 0xFFFFFFFF ) {
 
4872                         if ( strcmp(atom->getSegment().getName(), "__TEXT") == 0 )
 
4873                                 throwf("text relocs not supported for x86_64 in %s from %s",
 
4874                                                 atom->getDisplayName(), atom->getFile()->getPath());
 
4876                                 throwf("image too large: address can't fit in 32-bit r_address field in %s from %s",
 
4877                                                 atom->getDisplayName(), atom->getFile()->getPath());
 
4885 bool Writer<ppc>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref)
 
4887         switch ( ref.getKind() ) {
 
4888                 case ppc::kAbsLow16:
 
4889                 case ppc::kAbsLow14:
 
4890                 case ppc::kAbsHigh16:
 
4891                 case ppc::kAbsHigh16AddLow:
 
4900 bool Writer<ppc64>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref)
 
4902         switch ( ref.getKind() ) {
 
4903                 case ppc::kAbsLow16:
 
4904                 case ppc::kAbsLow14:
 
4905                 case ppc::kAbsHigh16:
 
4906                 case ppc::kAbsHigh16AddLow:
 
4914 bool Writer<x86>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref)
 
4916         if ( ref.getKind() == x86::kAbsolute32 ) {
 
4917                 switch ( ref.getTarget().getDefinitionKind() ) {
 
4918                         case ObjectFile::Atom::kTentativeDefinition:
 
4919                         case ObjectFile::Atom::kRegularDefinition:
 
4920                         case ObjectFile::Atom::kWeakDefinition:
 
4921                                 // illegal in dylibs/bundles, until we support TEXT relocs 
 
4923                         case ObjectFile::Atom::kExternalDefinition:
 
4924                         case ObjectFile::Atom::kExternalWeakDefinition:
 
4925                                 // illegal until we support TEXT relocs
 
4927                         case ObjectFile::Atom::kAbsoluteSymbol:
 
4928                                 // absolute symbbols only allowed in static executables
 
4929                                 return ( fOptions.outputKind() != Options::kStaticExecutable);
 
4936 bool Writer<x86_64>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref)
 
4938         if ( fOptions.outputKind() == Options::kKextBundle ) {
 
4939                 switch ( ref.getTarget().getDefinitionKind() ) {
 
4940                         case ObjectFile::Atom::kTentativeDefinition:
 
4941                         case ObjectFile::Atom::kRegularDefinition:
 
4942                         case ObjectFile::Atom::kWeakDefinition:
 
4943                         case ObjectFile::Atom::kAbsoluteSymbol:
 
4945                         case ObjectFile::Atom::kExternalDefinition:
 
4946                         case ObjectFile::Atom::kExternalWeakDefinition:
 
4947                                 // true means we need a TEXT relocs
 
4948                                 switch ( ref.getKind() ) {
 
4949                                         case x86_64::kBranchPCRel32:
 
4950                                         case x86_64::kBranchPCRel32WeakImport:
 
4951                                         case x86_64::kPCRel32GOTLoad:
 
4952                                         case x86_64::kPCRel32GOTLoadWeakImport:
 
4953                                         case x86_64::kPCRel32GOT:
 
4954                                         case x86_64::kPCRel32GOTWeakImport:
 
4964 bool Writer<arm>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref)
 
4966         switch ( fOptions.outputKind()) {
 
4967                 case Options::kStaticExecutable:
 
4968                 case Options::kPreload:
 
4969                         // all relocations allowed in static executables
 
4974         if ( ref.getKind() == arm::kReadOnlyPointer ) {
 
4975                 switch ( ref.getTarget().getDefinitionKind() ) {
 
4976                         case ObjectFile::Atom::kTentativeDefinition:
 
4977                         case ObjectFile::Atom::kRegularDefinition:
 
4978                         case ObjectFile::Atom::kWeakDefinition:
 
4979                                 // illegal in dylibs/bundles, until we support TEXT relocs 
 
4981                         case ObjectFile::Atom::kExternalDefinition:
 
4982                         case ObjectFile::Atom::kExternalWeakDefinition:
 
4983                                 // illegal until we support TEXT relocs
 
4985                         case ObjectFile::Atom::kAbsoluteSymbol:
 
4986                                 // absolute symbbols only allowed in static executables
 
4994 bool Writer<x86>::generatesLocalTextReloc(const ObjectFile::Reference& ref, const ObjectFile::Atom& atom, SectionInfo* atomSection)
 
4996         if ( ref.getKind() == x86::kAbsolute32 ) {
 
4997                 switch ( ref.getTarget().getDefinitionKind() ) {
 
4998                         case ObjectFile::Atom::kTentativeDefinition:
 
4999                         case ObjectFile::Atom::kRegularDefinition:
 
5000                         case ObjectFile::Atom::kWeakDefinition:
 
5001                                 // a reference to the absolute address of something in this same linkage unit can be 
 
5002                                 // encoded as a local text reloc in a dylib or bundle 
 
5004                                         macho_relocation_info<P> reloc;
 
5005                                         SectionInfo* sectInfo = (SectionInfo*)(ref.getTarget().getSection());
 
5006                                         reloc.set_r_address(this->relocAddressInFinalLinkedImage(atom.getAddress() + ref.getFixUpOffset(), &atom));
 
5007                                         reloc.set_r_symbolnum(sectInfo->getIndex());
 
5008                                         reloc.set_r_pcrel(false);
 
5009                                         reloc.set_r_length();
 
5010                                         reloc.set_r_extern(false);
 
5011                                         reloc.set_r_type(GENERIC_RELOC_VANILLA);
 
5012                                         fInternalRelocs.push_back(reloc);
 
5013                                         atomSection->fHasTextLocalRelocs = true;
 
5014                                         if ( fOptions.makeCompressedDyldInfo() ) {
 
5015                                                 fRebaseInfo.push_back(RebaseInfo(REBASE_TYPE_TEXT_ABSOLUTE32, atom.getAddress() + ref.getFixUpOffset()));
 
5020                         case ObjectFile::Atom::kExternalDefinition:
 
5021                         case ObjectFile::Atom::kExternalWeakDefinition:
 
5022                         case ObjectFile::Atom::kAbsoluteSymbol:
 
5030 bool Writer<ppc>::generatesLocalTextReloc(const ObjectFile::Reference& ref, const ObjectFile::Atom& atom, SectionInfo* atomSection)
 
5032         macho_relocation_info<P> reloc1;
 
5033         macho_relocation_info<P> reloc2;
 
5034         switch ( ref.getTarget().getDefinitionKind() ) {
 
5035                 case ObjectFile::Atom::kTentativeDefinition:
 
5036                 case ObjectFile::Atom::kRegularDefinition:
 
5037                 case ObjectFile::Atom::kWeakDefinition:
 
5038                         switch ( ref.getKind() ) {
 
5039                                 case ppc::kAbsLow16:
 
5040                                 case ppc::kAbsLow14:
 
5041                                         // a reference to the absolute address of something in this same linkage unit can be 
 
5042                                         // encoded as a local text reloc in a dylib or bundle 
 
5044                                                 SectionInfo* sectInfo = (SectionInfo*)(ref.getTarget().getSection());
 
5045                                                 uint32_t targetAddr = ref.getTarget().getAddress() + ref.getTargetOffset();
 
5046                                                 reloc1.set_r_address(this->relocAddressInFinalLinkedImage(atom.getAddress() + ref.getFixUpOffset(), &atom));
 
5047                                                 reloc1.set_r_symbolnum(sectInfo->getIndex());
 
5048                                                 reloc1.set_r_pcrel(false);
 
5049                                                 reloc1.set_r_length(2);
 
5050                                                 reloc1.set_r_extern(false);
 
5051                                                 reloc1.set_r_type(ref.getKind()==ppc::kAbsLow16 ? PPC_RELOC_LO16 : PPC_RELOC_LO14);
 
5052                                                 reloc2.set_r_address(targetAddr >> 16);
 
5053                                                 reloc2.set_r_symbolnum(0);
 
5054                                                 reloc2.set_r_pcrel(false);
 
5055                                                 reloc2.set_r_length(2);
 
5056                                                 reloc2.set_r_extern(false);
 
5057                                                 reloc2.set_r_type(PPC_RELOC_PAIR);
 
5058                                                 fInternalRelocs.push_back(reloc1);
 
5059                                                 fInternalRelocs.push_back(reloc2);
 
5060                                                 atomSection->fHasTextLocalRelocs = true;
 
5064                                 case ppc::kAbsHigh16:
 
5065                                 case ppc::kAbsHigh16AddLow:
 
5067                                                 SectionInfo* sectInfo = (SectionInfo*)(ref.getTarget().getSection());
 
5068                                                 uint32_t targetAddr = ref.getTarget().getAddress() + ref.getTargetOffset();
 
5069                                                 reloc1.set_r_address(this->relocAddressInFinalLinkedImage(atom.getAddress() + ref.getFixUpOffset(), &atom));
 
5070                                                 reloc1.set_r_symbolnum(sectInfo->getIndex());
 
5071                                                 reloc1.set_r_pcrel(false);
 
5072                                                 reloc1.set_r_length(2);
 
5073                                                 reloc1.set_r_extern(false);
 
5074                                                 reloc1.set_r_type(ref.getKind()==ppc::kAbsHigh16AddLow ? PPC_RELOC_HA16 : PPC_RELOC_HI16);
 
5075                                                 reloc2.set_r_address(targetAddr & 0xFFFF);
 
5076                                                 reloc2.set_r_symbolnum(0);
 
5077                                                 reloc2.set_r_pcrel(false);
 
5078                                                 reloc2.set_r_length(2);
 
5079                                                 reloc2.set_r_extern(false);
 
5080                                                 reloc2.set_r_type(PPC_RELOC_PAIR);
 
5081                                                 fInternalRelocs.push_back(reloc1);
 
5082                                                 fInternalRelocs.push_back(reloc2);
 
5083                                                 atomSection->fHasTextLocalRelocs = true;
 
5088                 case ObjectFile::Atom::kExternalDefinition:
 
5089                 case ObjectFile::Atom::kExternalWeakDefinition:
 
5090                 case ObjectFile::Atom::kAbsoluteSymbol:
 
5097 bool Writer<arm>::generatesLocalTextReloc(const ObjectFile::Reference& ref, const ObjectFile::Atom& atom, SectionInfo* atomSection)
 
5099         if ( ref.getKind() == arm::kReadOnlyPointer ) {
 
5100                 switch ( ref.getTarget().getDefinitionKind() ) {
 
5101                         case ObjectFile::Atom::kTentativeDefinition:
 
5102                         case ObjectFile::Atom::kRegularDefinition:
 
5103                         case ObjectFile::Atom::kWeakDefinition:
 
5104                                 // a reference to the absolute address of something in this same linkage unit can be 
 
5105                                 // encoded as a local text reloc in a dylib or bundle 
 
5107                                         macho_relocation_info<P> reloc;
 
5108                                         SectionInfo* sectInfo = (SectionInfo*)(ref.getTarget().getSection());
 
5109                                         reloc.set_r_address(this->relocAddressInFinalLinkedImage(atom.getAddress() + ref.getFixUpOffset(), &atom));
 
5110                                         reloc.set_r_symbolnum(sectInfo->getIndex());
 
5111                                         reloc.set_r_pcrel(false);
 
5112                                         reloc.set_r_length();
 
5113                                         reloc.set_r_extern(false);
 
5114                                         reloc.set_r_type(GENERIC_RELOC_VANILLA);
 
5115                                         fInternalRelocs.push_back(reloc);
 
5116                                         atomSection->fHasTextLocalRelocs = true;
 
5117                                         if ( fOptions.makeCompressedDyldInfo() ) {
 
5118                                                 fRebaseInfo.push_back(RebaseInfo(REBASE_TYPE_TEXT_ABSOLUTE32, atom.getAddress() + ref.getFixUpOffset()));
 
5123                         case ObjectFile::Atom::kExternalDefinition:
 
5124                         case ObjectFile::Atom::kExternalWeakDefinition:
 
5125                         case ObjectFile::Atom::kAbsoluteSymbol:
 
5134 bool Writer<x86_64>::generatesLocalTextReloc(const ObjectFile::Reference&, const ObjectFile::Atom& atom, SectionInfo* curSection)
 
5136         // text relocs not supported (usually never needed because of RIP addressing)
 
5141 bool Writer<ppc64>::generatesLocalTextReloc(const ObjectFile::Reference&, const ObjectFile::Atom& atom, SectionInfo* curSection)
 
5143         // text relocs not supported
 
5148 bool Writer<x86>::generatesExternalTextReloc(const ObjectFile::Reference& ref, const ObjectFile::Atom& atom, SectionInfo* atomSection)
 
5150         if ( ref.getKind() == x86::kAbsolute32 ) {
 
5151                 macho_relocation_info<P> reloc;
 
5152                 switch ( ref.getTarget().getDefinitionKind() ) {
 
5153                         case ObjectFile::Atom::kTentativeDefinition:
 
5154                         case ObjectFile::Atom::kRegularDefinition:
 
5155                         case ObjectFile::Atom::kWeakDefinition:
 
5157                         case ObjectFile::Atom::kExternalDefinition:
 
5158                         case ObjectFile::Atom::kExternalWeakDefinition:
 
5159                                 // a reference to the absolute address of something in another linkage unit can be 
 
5160                                 // encoded as an external text reloc in a dylib or bundle 
 
5161                                 reloc.set_r_address(this->relocAddressInFinalLinkedImage(atom.getAddress() + ref.getFixUpOffset(), &atom));
 
5162                                 reloc.set_r_symbolnum(this->symbolIndex(ref.getTarget()));
 
5163                                 reloc.set_r_pcrel(false);
 
5164                                 reloc.set_r_length();
 
5165                                 reloc.set_r_extern(true);
 
5166                                 reloc.set_r_type(GENERIC_RELOC_VANILLA);
 
5167                                 fExternalRelocs.push_back(reloc);
 
5168                                 atomSection->fHasTextExternalRelocs = true;
 
5170                         case ObjectFile::Atom::kAbsoluteSymbol:
 
5178 bool Writer<x86_64>::generatesExternalTextReloc(const ObjectFile::Reference& ref, const ObjectFile::Atom& atom, SectionInfo* atomSection)
 
5180         if ( fOptions.outputKind() == Options::kKextBundle ) {
 
5181                 macho_relocation_info<P> reloc;
 
5182                 switch ( ref.getTarget().getDefinitionKind() ) {
 
5183                         case ObjectFile::Atom::kTentativeDefinition:
 
5184                         case ObjectFile::Atom::kRegularDefinition:
 
5185                         case ObjectFile::Atom::kWeakDefinition:
 
5186                         case ObjectFile::Atom::kAbsoluteSymbol:
 
5188                         case ObjectFile::Atom::kExternalDefinition:
 
5189                         case ObjectFile::Atom::kExternalWeakDefinition:
 
5190                                 switch ( ref.getKind() ) {
 
5191                                         case x86_64::kBranchPCRel32:
 
5192                                         case x86_64::kBranchPCRel32WeakImport:
 
5193                                                 // a branch to something in another linkage unit is
 
5194                                                 // encoded as an external text reloc in a kext bundle 
 
5195                                                 reloc.set_r_address(this->relocAddressInFinalLinkedImage(atom.getAddress() + ref.getFixUpOffset(), &atom));
 
5196                                                 reloc.set_r_symbolnum(this->symbolIndex(ref.getTarget()));
 
5197                                                 reloc.set_r_pcrel(true);
 
5198                                                 reloc.set_r_length(2);
 
5199                                                 reloc.set_r_extern(true);
 
5200                                                 reloc.set_r_type(X86_64_RELOC_BRANCH);
 
5201                                                 fExternalRelocs.push_back(reloc);
 
5202                                                 atomSection->fHasTextExternalRelocs = true;
 
5204                                         case x86_64::kPCRel32GOTLoad:
 
5205                                         case x86_64::kPCRel32GOTLoadWeakImport:
 
5206                                                 // a load of the GOT entry for a symbol in another linkage unit is 
 
5207                                                 // encoded as an external text reloc in a kext bundle 
 
5208                                                 reloc.set_r_address(this->relocAddressInFinalLinkedImage(atom.getAddress() + ref.getFixUpOffset(), &atom));
 
5209                                                 reloc.set_r_symbolnum(this->symbolIndex(ref.getTarget()));
 
5210                                                 reloc.set_r_pcrel(true);
 
5211                                                 reloc.set_r_length(2);
 
5212                                                 reloc.set_r_extern(true);
 
5213                                                 reloc.set_r_type(X86_64_RELOC_GOT_LOAD);
 
5214                                                 fExternalRelocs.push_back(reloc);
 
5215                                                 atomSection->fHasTextExternalRelocs = true;
 
5217                                         case x86_64::kPCRel32GOT:
 
5218                                         case x86_64::kPCRel32GOTWeakImport:
 
5219                                                 // a use of the GOT entry for a symbol in another linkage unit is 
 
5220                                                 // encoded as an external text reloc in a kext bundle 
 
5221                                                 reloc.set_r_address(this->relocAddressInFinalLinkedImage(atom.getAddress() + ref.getFixUpOffset(), &atom));
 
5222                                                 reloc.set_r_symbolnum(this->symbolIndex(ref.getTarget()));
 
5223                                                 reloc.set_r_pcrel(true);
 
5224                                                 reloc.set_r_length(2);
 
5225                                                 reloc.set_r_extern(true);
 
5226                                                 reloc.set_r_type(X86_64_RELOC_GOT);
 
5227                                                 fExternalRelocs.push_back(reloc);
 
5228                                                 atomSection->fHasTextExternalRelocs = true;
 
5238 template <typename A>
 
5239 bool Writer<A>::generatesExternalTextReloc(const ObjectFile::Reference&, const ObjectFile::Atom& atom, SectionInfo* curSection)
 
5247 template <typename A>
 
5248 typename Writer<A>::RelocKind Writer<A>::relocationNeededInFinalLinkedImage(const ObjectFile::Atom& target) const
 
5250         switch ( target.getDefinitionKind() ) {
 
5251                 case ObjectFile::Atom::kTentativeDefinition:
 
5252                 case ObjectFile::Atom::kRegularDefinition:
 
5253                         // in main executables, the only way regular symbols are indirected is if -interposable is used
 
5254                         if ( fOptions.outputKind() == Options::kDynamicExecutable ) {
 
5255                                 if ( this->shouldExport(target) && fOptions.interposable(target.getName()) )
 
5256                                         return kRelocExternal;
 
5257                                 else if ( fSlideable )
 
5258                                         return kRelocInternal;
 
5262                         // for flat-namespace or interposable two-level-namespace
 
5263                         // all references to exported symbols get indirected
 
5264                         else if ( this->shouldExport(target) &&
 
5265                            ((fOptions.nameSpace() == Options::kFlatNameSpace)
 
5266                           || (fOptions.nameSpace() == Options::kForceFlatNameSpace)
 
5267                           || fOptions.interposable(target.getName())) 
 
5268                           && (target.getName() != NULL) 
 
5269                           && (strncmp(target.getName(), ".objc_class_", 12) != 0) ) // <rdar://problem/5254468>
 
5270                                 return kRelocExternal;
 
5271                         else if ( fSlideable )
 
5272                                 return kRelocInternal;
 
5275                 case ObjectFile::Atom::kWeakDefinition:
 
5276                         // all calls to global weak definitions get indirected
 
5277                         if ( this->shouldExport(target) )
 
5278                                 return kRelocExternal;
 
5279                         else if ( fSlideable )
 
5280                                 return kRelocInternal;
 
5283                 case ObjectFile::Atom::kExternalDefinition:
 
5284                 case ObjectFile::Atom::kExternalWeakDefinition:
 
5285                         return kRelocExternal;
 
5286                 case ObjectFile::Atom::kAbsoluteSymbol:
 
5292 template <typename A>
 
5293 uint64_t Writer<A>::relocAddressInFinalLinkedImage(uint64_t address, const ObjectFile::Atom* atom) const
 
5295         // for 32-bit architectures, the r_address field in relocs
 
5296         // for final linked images is the offset from the first segment
 
5297         uint64_t result = address - fSegmentInfos[0]->fBaseAddress;
 
5298         if ( fOptions.outputKind() == Options::kPreload ) {
 
5299                 // kPreload uses a virtual __HEADER segment to cover the load commands
 
5300                 result = address - fSegmentInfos[1]->fBaseAddress;
 
5302         // or the offset from the first writable segment if built split-seg
 
5303         if ( fOptions.splitSeg() )
 
5304                 result = address - fFirstWritableSegment->fBaseAddress;
 
5305         if ( result > 0x7FFFFFFF ) {
 
5306                 throwf("image too large: address can't fit in 31-bit r_address field in %s from %s",
 
5307                         atom->getDisplayName(), atom->getFile()->getPath());
 
5313 uint64_t Writer<ppc64>::relocAddressInFinalLinkedImage(uint64_t address, const ObjectFile::Atom* atom)  const
 
5315         // for ppc64, the Mac OS X 10.4 dyld assumes r_address is always the offset from the base address.  
 
5316         // the 10.5 dyld, iterprets the r_address as:
 
5317         //   1) an offset from the base address, iff there are no writable segments with a address > 4GB from base address, otherwise
 
5318         //   2) an offset from the base address of the first writable segment
 
5319         // For dyld, r_address is always the offset from the base address
 
5321         bool badFor10_4 = false;
 
5322         if ( fWritableSegmentPastFirst4GB ) {
 
5323                 if ( fOptions.macosxVersionMin() < ObjectFile::ReaderOptions::k10_5 )
 
5325                 result = address - fFirstWritableSegment->fBaseAddress;
 
5326                 if ( result > 0xFFFFFFFF ) {
 
5327                         throwf("image too large: address can't fit in 32-bit r_address field in %s from %s",
 
5328                                 atom->getDisplayName(), atom->getFile()->getPath());
 
5332                 result = address - fSegmentInfos[0]->fBaseAddress;
 
5333                 if ( (fOptions.macosxVersionMin() < ObjectFile::ReaderOptions::k10_5) && (result > 0x7FFFFFFF) )
 
5337                         throwf("image or pagezero_size too large for Mac OS X 10.4: address can't fit in 31-bit r_address field for %s from %s",
 
5338                                 atom->getDisplayName(), atom->getFile()->getPath());
 
5344 template <> bool    Writer<ppc>::preboundLazyPointerType(uint8_t* type) { *type = PPC_RELOC_PB_LA_PTR; return true; }
 
5345 template <> bool  Writer<ppc64>::preboundLazyPointerType(uint8_t* type) { throw "prebinding not supported"; }
 
5346 template <> bool    Writer<x86>::preboundLazyPointerType(uint8_t* type) { *type = GENERIC_RELOC_PB_LA_PTR; return true; }
 
5347 template <> bool Writer<x86_64>::preboundLazyPointerType(uint8_t* type) { throw "prebinding not supported"; }
 
5348 template <> bool    Writer<arm>::preboundLazyPointerType(uint8_t* type) { *type = ARM_RELOC_PB_LA_PTR; return true; }
 
5350 template <typename A>
 
5351 void Writer<A>::buildExecutableFixups()
 
5353         if ( fIndirectTableAtom != NULL )
 
5354                 fIndirectTableAtom->fTable.reserve(50);  // minimize reallocations
 
5355         std::vector<SegmentInfo*>& segmentInfos = fSegmentInfos;
 
5356         const int segCount = segmentInfos.size();
 
5357         for(int i=0; i < segCount; ++i) {
 
5358                 SegmentInfo* curSegment = segmentInfos[i];
 
5359                 std::vector<SectionInfo*>& sectionInfos = curSegment->fSections;
 
5360                 const int sectionCount = sectionInfos.size();
 
5361                 for(int j=0; j < sectionCount; ++j) {
 
5362                         SectionInfo* curSection = sectionInfos[j];
 
5363                         //fprintf(stderr, "starting section %s\n", curSection->fSectionName);
 
5364                         std::vector<ObjectFile::Atom*>& sectionAtoms = curSection->fAtoms;
 
5365                         if ( ! curSection->fAllZeroFill ) {
 
5366                                 if ( curSection->fAllNonLazyPointers || curSection->fAllLazyPointers || curSection->fAllLazyDylibPointers 
 
5367                                                                                                 || curSection->fAllStubs || curSection->fAllSelfModifyingStubs ) {
 
5368                                         if ( fIndirectTableAtom != NULL )
 
5369                                                 curSection->fIndirectSymbolOffset = fIndirectTableAtom->fTable.size();
 
5371                                 const int atomCount = sectionAtoms.size();
 
5372                                 for (int k=0; k < atomCount; ++k) {
 
5373                                         ObjectFile::Atom* atom = sectionAtoms[k];
 
5374                                         std::vector<ObjectFile::Reference*>& refs = atom->getReferences();
 
5375                                         const int refCount = refs.size();
 
5376                                         //fprintf(stderr, "atom %s has %d references in section %s, %p\n", atom->getDisplayName(), refCount, curSection->fSectionName, atom->getSection());
 
5377                                         if ( curSection->fAllNonLazyPointers && (refCount == 0) ) {
 
5378                                                 // handle imageloadercache GOT slot
 
5379                                                 uint32_t offsetInSection = atom->getSectionOffset();
 
5380                                                 uint32_t indexInSection = offsetInSection / sizeof(pint_t);
 
5381                                                 uint32_t indirectTableIndex = indexInSection + curSection->fIndirectSymbolOffset;
 
5382                                                 // use INDIRECT_SYMBOL_ABS so 10.5 dyld will leave value as zero
 
5383                                                 IndirectEntry entry = { indirectTableIndex, INDIRECT_SYMBOL_ABS };
 
5384                                                 //fprintf(stderr,"fIndirectTableAtom->fTable.push_back(tableIndex=%d, symIndex=0x%X, section=%s)\n", 
 
5385                                                 //              indirectTableIndex, INDIRECT_SYMBOL_LOCAL, curSection->fSectionName);
 
5386                                                 fIndirectTableAtom->fTable.push_back(entry);
 
5388                                         for (int l=0; l < refCount; ++l) {
 
5389                                                 ObjectFile::Reference* ref = refs[l];
 
5390                                                 if ( (fOptions.outputKind() != Options::kKextBundle) && 
 
5391                                                                 (curSection->fAllNonLazyPointers || curSection->fAllLazyPointers || curSection->fAllLazyDylibPointers) ) {
 
5392                                                         // if atom is in (non)lazy_pointer section, this is encoded as an indirect symbol
 
5393                                                         if ( atom->getSize() != sizeof(pint_t) ) {
 
5394                                                                 warning("wrong size pointer atom %s from file %s", atom->getDisplayName(), atom->getFile()->getPath());
 
5396                                                         ObjectFile::Atom* pointerTarget = &(ref->getTarget());
 
5397                                                         if ( curSection->fAllLazyPointers || curSection->fAllLazyDylibPointers ) {
 
5398                                                                 pointerTarget = ((LazyPointerAtom<A>*)atom)->getTarget();
 
5400                                                         uint32_t offsetInSection = atom->getSectionOffset();
 
5401                                                         uint32_t indexInSection = offsetInSection / sizeof(pint_t);
 
5402                                                         uint32_t undefinedSymbolIndex = INDIRECT_SYMBOL_LOCAL;
 
5403                                                         if  (atom == fFastStubGOTAtom)
 
5404                                                                 undefinedSymbolIndex = INDIRECT_SYMBOL_ABS;
 
5405                                                         else if ( this->relocationNeededInFinalLinkedImage(*pointerTarget) == kRelocExternal )
 
5406                                                                 undefinedSymbolIndex = this->symbolIndex(*pointerTarget);
 
5407                                                         uint32_t indirectTableIndex = indexInSection + curSection->fIndirectSymbolOffset;
 
5408                                                         IndirectEntry entry = { indirectTableIndex, undefinedSymbolIndex };
 
5409                                                         //fprintf(stderr,"fIndirectTableAtom->fTable.push_back(tableIndex=%d, symIndex=0x%X, section=%s)\n", 
 
5410                                                         //              indirectTableIndex, undefinedSymbolIndex, curSection->fSectionName);
 
5411                                                         fIndirectTableAtom->fTable.push_back(entry);
 
5412                                                         if ( curSection->fAllLazyPointers || curSection->fAllLazyDylibPointers ) {
 
5413                                                                 uint8_t preboundLazyType;
 
5414                                                                 if ( fOptions.prebind() && (fDyldClassicHelperAtom != NULL) 
 
5415                                                                                 && curSection->fAllLazyPointers && preboundLazyPointerType(&preboundLazyType) ) {
 
5416                                                                         // this is a prebound image, need special relocs for dyld to reset lazy pointers if prebinding is invalid
 
5417                                                                         macho_scattered_relocation_info<P> pblaReloc;
 
5418                                                                         pblaReloc.set_r_scattered(true);
 
5419                                                                         pblaReloc.set_r_pcrel(false);
 
5420                                                                         pblaReloc.set_r_length();
 
5421                                                                         pblaReloc.set_r_type(preboundLazyType);
 
5422                                                                         pblaReloc.set_r_address(relocAddressInFinalLinkedImage(atom->getAddress(), atom));
 
5423                                                                         pblaReloc.set_r_value(fDyldClassicHelperAtom->getAddress());
 
5424                                                                         fInternalRelocs.push_back(*((macho_relocation_info<P>*)&pblaReloc));
 
5426                                                                 else if ( fSlideable ) {
 
5427                                                                         // this is a non-prebound dylib/bundle, need vanilla internal relocation to fix up binding handler if image slides
 
5428                                                                         macho_relocation_info<P> dyldHelperReloc;
 
5429                                                                         uint32_t sectionNum = 1;
 
5430                                                                         if ( fDyldClassicHelperAtom != NULL )
 
5431                                                                                 sectionNum = ((SectionInfo*)(fDyldClassicHelperAtom->getSection()))->getIndex();
 
5432                                                                         //fprintf(stderr, "lazy pointer reloc, section index=%u, section name=%s\n", sectionNum, curSection->fSectionName);
 
5433                                                                         dyldHelperReloc.set_r_address(relocAddressInFinalLinkedImage(atom->getAddress(), atom));
 
5434                                                                         dyldHelperReloc.set_r_symbolnum(sectionNum);
 
5435                                                                         dyldHelperReloc.set_r_pcrel(false);
 
5436                                                                         dyldHelperReloc.set_r_length();
 
5437                                                                         dyldHelperReloc.set_r_extern(false);
 
5438                                                                         dyldHelperReloc.set_r_type(GENERIC_RELOC_VANILLA);
 
5439                                                                         fInternalRelocs.push_back(dyldHelperReloc);
 
5440                                                                         if ( fOptions.makeCompressedDyldInfo() ) {
 
5441                                                                                 fRebaseInfo.push_back(RebaseInfo(REBASE_TYPE_POINTER,atom->getAddress()));
 
5444                                                                 if ( fOptions.makeCompressedDyldInfo() ) {
 
5445                                                                         uint8_t type = BIND_TYPE_POINTER;
 
5446                                                                         uint64_t addresss = atom->getAddress() + ref->getFixUpOffset();
 
5447                                                                         if ( pointerTarget->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition ) {
 
5448                                                                                 // This is a referece to a weak def in some dylib (e.g. operator new)
 
5449                                                                                 // need to bind into to directly bind this
 
5450                                                                                 // later weak binding info may override
 
5451                                                                                 int ordinal = compressedOrdinalForImortedAtom(pointerTarget);
 
5452                                                                                 fBindingInfo.push_back(BindingInfo(type, ordinal, pointerTarget->getName(), false, addresss, 0));
 
5454                                                                         if ( targetRequiresWeakBinding(*pointerTarget) ) {
 
5455                                                                                 // note: lazy pointers to weak symbols are not bound lazily
 
5456                                                                                 fWeakBindingInfo.push_back(BindingInfo(type, pointerTarget->getName(), false, addresss, 0));
 
5460                                                         if ( curSection->fAllNonLazyPointers && fOptions.makeCompressedDyldInfo() ) {
 
5461                                                                 if ( pointerTarget != NULL ) {
 
5462                                                                         switch ( this->relocationNeededInFinalLinkedImage(*pointerTarget) ) {
 
5464                                                                                 // no rebase or binding info needed
 
5466                                                                                 case kRelocInternal:
 
5467                                                                                         // a non-lazy pointer that has been optimized to LOCAL needs rebasing info
 
5468                                                                                         // but not the magic fFastStubGOTAtom atom
 
5469                                                                                         if  (atom != fFastStubGOTAtom)
 
5470                                                                                                 fRebaseInfo.push_back(RebaseInfo(REBASE_TYPE_POINTER,atom->getAddress()));
 
5472                                                                                 case kRelocExternal:
 
5474                                                                                         uint8_t type = BIND_TYPE_POINTER;
 
5475                                                                                         uint64_t addresss = atom->getAddress();
 
5476                                                                                         if ( targetRequiresWeakBinding(ref->getTarget()) ) {
 
5477                                                                                                 fWeakBindingInfo.push_back(BindingInfo(type, ref->getTarget().getName(), false, addresss, 0));
 
5478                                                                                                 // if this is a non-lazy pointer to a weak definition within this linkage unit
 
5479                                                                                                 // the pointer needs to initially point within linkage unit and have
 
5480                                                                                                 // rebase command to slide it.
 
5481                                                                                                 if ( ref->getTarget().getDefinitionKind() == ObjectFile::Atom::kWeakDefinition ) {
 
5482                                                                                                         // unless if this is a hybrid format, in which case the non-lazy pointer
 
5483                                                                                                         // is zero on disk.  So use a bind instead of a rebase to set initial value
 
5484                                                                                                         if ( fOptions.makeClassicDyldInfo() )
 
5485                                                                                                                 fBindingInfo.push_back(BindingInfo(type, BIND_SPECIAL_DYLIB_SELF, ref->getTarget().getName(), false, addresss, 0));
 
5487                                                                                                                 fRebaseInfo.push_back(RebaseInfo(REBASE_TYPE_POINTER,atom->getAddress()));
 
5489                                                                                                 // if this is a non-lazy pointer to a weak definition in a dylib,
 
5490                                                                                                 // the pointer needs to initially bind to the dylib
 
5491                                                                                                 else if ( ref->getTarget().getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition ) {
 
5492                                                                                                         int ordinal = compressedOrdinalForImortedAtom(pointerTarget);
 
5493                                                                                                         fBindingInfo.push_back(BindingInfo(BIND_TYPE_POINTER, ordinal, pointerTarget->getName(), false, addresss, 0));
 
5497                                                                                                 int ordinal = compressedOrdinalForImortedAtom(pointerTarget);
 
5498                                                                                                 bool weak_import = fWeakImportMap[pointerTarget];
 
5499                                                                                                 fBindingInfo.push_back(BindingInfo(type, ordinal, ref->getTarget().getName(), weak_import, addresss, 0));
 
5506                                                 else if ( (ref->getKind() == A::kPointer) || (ref->getKind() == A::kPointerWeakImport) ) {
 
5507                                                         if ( fSlideable && ((curSegment->fInitProtection & VM_PROT_WRITE) == 0) ) {
 
5508                                                                 if ( fOptions.allowTextRelocs() ) {
 
5509                                                                         if ( fOptions.warnAboutTextRelocs() )
 
5510                                                                                 warning("text reloc in %s to %s", atom->getDisplayName(), ref->getTargetName());
 
5513                                                                         throwf("pointer in read-only segment not allowed in slidable image, used in %s from %s",
 
5514                                                                                 atom->getDisplayName(), atom->getFile()->getPath());
 
5517                                                         switch ( this->relocationNeededInFinalLinkedImage(ref->getTarget()) ) {
 
5521                                                                 case kRelocInternal:
 
5523                                                                                 macho_relocation_info<P> internalReloc;
 
5524                                                                                 SectionInfo* sectInfo = (SectionInfo*)ref->getTarget().getSection();
 
5525                                                                                 uint32_t sectionNum = sectInfo->getIndex();
 
5526                                                                                 // special case _mh_dylib_header and friends which are not in any real section
 
5527                                                                                 if ( (sectionNum ==0) && sectInfo->fVirtualSection && (strcmp(sectInfo->fSectionName, "._mach_header") == 0) )
 
5529                                                                                 internalReloc.set_r_address(this->relocAddressInFinalLinkedImage(atom->getAddress() + ref->getFixUpOffset(), atom));
 
5530                                                                                 internalReloc.set_r_symbolnum(sectionNum);
 
5531                                                                                 internalReloc.set_r_pcrel(false);
 
5532                                                                                 internalReloc.set_r_length();
 
5533                                                                                 internalReloc.set_r_extern(false);
 
5534                                                                                 internalReloc.set_r_type(GENERIC_RELOC_VANILLA);
 
5535                                                                                 fInternalRelocs.push_back(internalReloc);
 
5536                                                                                 if ( fOptions.makeCompressedDyldInfo() ) {
 
5537                                                                                         fRebaseInfo.push_back(RebaseInfo(REBASE_TYPE_POINTER, atom->getAddress() + ref->getFixUpOffset()));
 
5541                                                                 case kRelocExternal:
 
5543                                                                                 macho_relocation_info<P> externalReloc;
 
5544                                                                                 externalReloc.set_r_address(this->relocAddressInFinalLinkedImage(atom->getAddress() + ref->getFixUpOffset(), atom));
 
5545                                                                                 externalReloc.set_r_symbolnum(this->symbolIndex(ref->getTarget()));
 
5546                                                                                 externalReloc.set_r_pcrel(false);
 
5547                                                                                 externalReloc.set_r_length();
 
5548                                                                                 externalReloc.set_r_extern(true);
 
5549                                                                                 externalReloc.set_r_type(GENERIC_RELOC_VANILLA);
 
5550                                                                                 fExternalRelocs.push_back(externalReloc);
 
5551                                                                                 if ( fOptions.makeCompressedDyldInfo() ) {
 
5552                                                                                         int64_t addend = ref->getTargetOffset();
 
5553                                                                                         uint64_t addresss = atom->getAddress() + ref->getFixUpOffset();
 
5554                                                                                         if ( !fOptions.makeClassicDyldInfo() ) {
 
5555                                                                                                 if ( ref->getTarget().getDefinitionKind() == ObjectFile::Atom::kWeakDefinition ) {
 
5556                                                                                                         // pointers to internal weak defs need a rebase
 
5557                                                                                                         fRebaseInfo.push_back(RebaseInfo(REBASE_TYPE_POINTER, addresss));
 
5560                                                                                         uint8_t type = BIND_TYPE_POINTER;
 
5561                                                                                         if ( targetRequiresWeakBinding(ref->getTarget()) ) {
 
5562                                                                                                 fWeakBindingInfo.push_back(BindingInfo(type, ref->getTarget().getName(), false, addresss, addend));
 
5563                                                                                                 if ( fOptions.makeClassicDyldInfo() && (ref->getTarget().getDefinitionKind() == ObjectFile::Atom::kWeakDefinition) ) {
 
5564                                                                                                         // hybrid linkedit puts addend in data, so we need bind phase to reset pointer to local definifion
 
5565                                                                                                         fBindingInfo.push_back(BindingInfo(type, BIND_SPECIAL_DYLIB_SELF, ref->getTarget().getName(), false, addresss, addend));
 
5567                                                                                                 // if this is a pointer to a weak definition in a dylib,
 
5568                                                                                                 // the pointer needs to initially bind to the dylib
 
5569                                                                                                 else if ( ref->getTarget().getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition ) {
 
5570                                                                                                         int ordinal = compressedOrdinalForImortedAtom(&ref->getTarget());
 
5571                                                                                                         fBindingInfo.push_back(BindingInfo(BIND_TYPE_POINTER, ordinal, ref->getTarget().getName(), false, addresss, addend));
 
5575                                                                                                 int ordinal = compressedOrdinalForImortedAtom(&ref->getTarget());
 
5576                                                                                                 bool weak_import = fWeakImportMap[&(ref->getTarget())];
 
5577                                                                                                 fBindingInfo.push_back(BindingInfo(type, ordinal, ref->getTarget().getName(), weak_import, addresss, addend));
 
5584                                                 else if ( this->illegalRelocInFinalLinkedImage(*ref) ) {
 
5585                                                         // new x86 stubs always require text relocs
 
5586                                                         if ( curSection->fAllStubs || curSection->fAllStubHelpers ) {
 
5587                                                                 if ( this->generatesLocalTextReloc(*ref, *atom, curSection) ) {
 
5588                                                                         // relocs added to fInternalRelocs
 
5591                                                         else if ( fOptions.allowTextRelocs() && !atom->getSegment().isContentWritable() ) {
 
5592                                                                 if ( fOptions.warnAboutTextRelocs() )
 
5593                                                                         warning("text reloc in %s to %s", atom->getDisplayName(), ref->getTargetName());
 
5594                                                                 if (  this->generatesLocalTextReloc(*ref, *atom, curSection) ) {
 
5595                                                                         // relocs added to fInternalRelocs
 
5597                                                                 else if ( this->generatesExternalTextReloc(*ref, *atom, curSection) ) {
 
5598                                                                         // relocs added to fExternalRelocs
 
5601                                                                         throwf("relocation used in %s from %s not allowed in slidable image", atom->getDisplayName(), atom->getFile()->getPath());
 
5605                                                                 throwf("absolute addressing (perhaps -mdynamic-no-pic) used in %s from %s not allowed in slidable image. "
 
5606                                                                                 "Use '-read_only_relocs suppress' to enable text relocs", atom->getDisplayName(), atom->getFile()->getPath());
 
5610                                         if ( curSection->fAllSelfModifyingStubs || curSection->fAllStubs ) {
 
5611                                                 ObjectFile::Atom* stubTarget = ((StubAtom<A>*)atom)->getTarget();
 
5612                                                 uint32_t undefinedSymbolIndex = (stubTarget != NULL) ? this->symbolIndex(*stubTarget) : INDIRECT_SYMBOL_ABS;
 
5613                                                 uint32_t offsetInSection = atom->getSectionOffset();
 
5614                                                 uint32_t indexInSection = offsetInSection / atom->getSize();
 
5615                                                 uint32_t indirectTableIndex = indexInSection + curSection->fIndirectSymbolOffset;
 
5616                                                 IndirectEntry entry = { indirectTableIndex, undefinedSymbolIndex };
 
5617                                                 //fprintf(stderr,"for stub: fIndirectTableAtom->fTable.add(%d-%d => 0x%X-%s), size=%lld\n", indexInSection, indirectTableIndex, undefinedSymbolIndex, stubTarget->getName(), atom->getSize());
 
5618                                                 fIndirectTableAtom->fTable.push_back(entry);
 
5624         if ( fSplitCodeToDataContentAtom != NULL )
 
5625                 fSplitCodeToDataContentAtom->encode();
 
5626         if ( fCompressedRebaseInfoAtom != NULL ) 
 
5627                 fCompressedRebaseInfoAtom->encode();
 
5628         if ( fCompressedBindingInfoAtom != NULL ) 
 
5629                 fCompressedBindingInfoAtom->encode();
 
5630         if ( fCompressedWeakBindingInfoAtom != NULL ) 
 
5631                 fCompressedWeakBindingInfoAtom->encode();
 
5632         if ( fCompressedLazyBindingInfoAtom != NULL ) 
 
5633                 fCompressedLazyBindingInfoAtom->encode();
 
5634         if ( fCompressedExportInfoAtom != NULL ) 
 
5635                 fCompressedExportInfoAtom->encode();
 
5640 void Writer<ppc>::addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref)
 
5642         switch ( (ppc::ReferenceKinds)ref->getKind() ) {
 
5643                 case ppc::kPICBaseHigh16:
 
5644                         fSplitCodeToDataContentAtom->addPPCHi16Location(atom, ref->getFixUpOffset());
 
5646                 case ppc::kPointerDiff32:
 
5647                         fSplitCodeToDataContentAtom->add32bitPointerLocation(atom, ref->getFixUpOffset());
 
5649                 case ppc::kPointerDiff64:
 
5650                         fSplitCodeToDataContentAtom->add64bitPointerLocation(atom, ref->getFixUpOffset());
 
5653                 case ppc::kGroupSubordinate:
 
5655                 case ppc::kPointerWeakImport:
 
5656                 case ppc::kPICBaseLow16:
 
5657                 case ppc::kPICBaseLow14:
 
5661                         warning("codegen with reference kind %d in %s prevents image from loading in dyld shared cache", ref->getKind(), atom->getDisplayName());
 
5662                         fSplitCodeToDataContentAtom->setCantEncode();
 
5667 void Writer<ppc64>::addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref)
 
5669         switch ( (ppc64::ReferenceKinds)ref->getKind()  ) {
 
5670                 case ppc64::kPICBaseHigh16:
 
5671                         fSplitCodeToDataContentAtom->addPPCHi16Location(atom, ref->getFixUpOffset());
 
5673                 case ppc64::kPointerDiff32:
 
5674                         fSplitCodeToDataContentAtom->add32bitPointerLocation(atom, ref->getFixUpOffset());
 
5676                 case ppc64::kPointerDiff64:
 
5677                         fSplitCodeToDataContentAtom->add64bitPointerLocation(atom, ref->getFixUpOffset());
 
5679                 case ppc64::kNoFixUp:
 
5680                 case ppc64::kGroupSubordinate:
 
5681                 case ppc64::kPointer:
 
5682                 case ppc64::kPointerWeakImport:
 
5683                 case ppc64::kPICBaseLow16:
 
5684                 case ppc64::kPICBaseLow14:
 
5688                         warning("codegen with reference kind %d in %s prevents image from loading in dyld shared cache", ref->getKind(), atom->getDisplayName());
 
5689                         fSplitCodeToDataContentAtom->setCantEncode();
 
5694 void Writer<x86>::addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref)
 
5696         switch ( (x86::ReferenceKinds)ref->getKind()  ) {
 
5697                 case x86::kPointerDiff:
 
5698                 case x86::kImageOffset32:
 
5699                         if ( strcmp(ref->getTarget().getSegment().getName(), "__IMPORT") == 0 ) 
 
5700                                 fSplitCodeToDataContentAtom->add32bitImportLocation(atom, ref->getFixUpOffset());
 
5702                                 fSplitCodeToDataContentAtom->add32bitPointerLocation(atom, ref->getFixUpOffset());
 
5705                 case x86::kGroupSubordinate:
 
5707                 case x86::kPointerWeakImport:
 
5711                 case x86::kPCRel32WeakImport:
 
5712                         if (    (&(ref->getTarget().getSegment()) == &Segment::fgImportSegment)
 
5713                                 ||  (&(ref->getTarget().getSegment()) == &Segment::fgROImportSegment) ) {
 
5714                                 fSplitCodeToDataContentAtom->add32bitImportLocation(atom, ref->getFixUpOffset());
 
5717                         // fall into warning case
 
5719                         if ( fOptions.makeCompressedDyldInfo() && (ref->getKind() == x86::kAbsolute32) ) {
 
5720                                 // will be encoded in rebase info
 
5723                                 warning("codegen in %s (offset 0x%08llX) prevents image from loading in dyld shared cache", atom->getDisplayName(), ref->getFixUpOffset());
 
5724                                 fSplitCodeToDataContentAtom->setCantEncode();
 
5730 void Writer<x86_64>::addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref)
 
5732         switch ( (x86_64::ReferenceKinds)ref->getKind()  ) {
 
5733                 case x86_64::kPCRel32:
 
5734                 case x86_64::kPCRel32_1:
 
5735                 case x86_64::kPCRel32_2:
 
5736                 case x86_64::kPCRel32_4:
 
5737                 case x86_64::kPCRel32GOTLoad:
 
5738                 case x86_64::kPCRel32GOTLoadWeakImport:
 
5739                 case x86_64::kPCRel32GOT:
 
5740                 case x86_64::kPCRel32GOTWeakImport:
 
5741                 case x86_64::kPointerDiff32:
 
5742                 case x86_64::kImageOffset32:
 
5743                         fSplitCodeToDataContentAtom->add32bitPointerLocation(atom, ref->getFixUpOffset());
 
5745                 case x86_64::kPointerDiff:
 
5746                         fSplitCodeToDataContentAtom->add64bitPointerLocation(atom, ref->getFixUpOffset());
 
5748                 case x86_64::kNoFixUp:
 
5749                 case x86_64::kGroupSubordinate:
 
5750                 case x86_64::kPointer:
 
5751                 case x86_64::kGOTNoFixUp:
 
5755                         warning("codegen in %s with kind %d prevents image from loading in dyld shared cache", atom->getDisplayName(), ref->getKind());
 
5756                         fSplitCodeToDataContentAtom->setCantEncode();
 
5761 void Writer<arm>::addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref)
 
5763         switch ( (arm::ReferenceKinds)ref->getKind()  ) {
 
5764                 case arm::kPointerDiff:
 
5765                         fSplitCodeToDataContentAtom->add32bitPointerLocation(atom, ref->getFixUpOffset());
 
5768                 case arm::kGroupSubordinate:
 
5770                 case arm::kPointerWeakImport:
 
5771                 case arm::kReadOnlyPointer:
 
5775                         warning("codegen in %s prevents image from loading in dyld shared cache", atom->getDisplayName());
 
5776                         fSplitCodeToDataContentAtom->setCantEncode();
 
5780 template <typename A>
 
5781 bool Writer<A>::segmentsCanSplitApart(const ObjectFile::Atom& from, const ObjectFile::Atom& to)
 
5783         switch ( to.getDefinitionKind() ) {
 
5784                 case ObjectFile::Atom::kExternalDefinition:
 
5785                 case ObjectFile::Atom::kExternalWeakDefinition:
 
5786                 case ObjectFile::Atom::kAbsoluteSymbol:
 
5788                 case ObjectFile::Atom::kRegularDefinition:
 
5789                 case ObjectFile::Atom::kWeakDefinition:
 
5790                 case ObjectFile::Atom::kTentativeDefinition:
 
5791                         // segments with same permissions slide together
 
5792                         return ( (from.getSegment().isContentExecutable() != to.getSegment().isContentExecutable())
 
5793                                         || (from.getSegment().isContentWritable() != to.getSegment().isContentWritable()) );
 
5795         throw "ld64 internal error";
 
5800 void Writer<ppc>::writeNoOps(int fd, uint32_t from, uint32_t to)
 
5803         OSWriteBigInt32(&ppcNop, 0, 0x60000000);
 
5804         for (uint32_t p=from; p < to; p += 4)
 
5805                 ::pwrite(fd, &ppcNop, 4, p);
 
5809 void Writer<ppc64>::writeNoOps(int fd, uint32_t from, uint32_t to)
 
5812         OSWriteBigInt32(&ppcNop, 0, 0x60000000);
 
5813         for (uint32_t p=from; p < to; p += 4)
 
5814                 ::pwrite(fd, &ppcNop, 4, p);
 
5818 void Writer<x86>::writeNoOps(int fd, uint32_t from, uint32_t to)
 
5820         uint8_t x86Nop = 0x90;
 
5821         for (uint32_t p=from; p < to; ++p)
 
5822                 ::pwrite(fd, &x86Nop, 1, p);
 
5826 void Writer<x86_64>::writeNoOps(int fd, uint32_t from, uint32_t to)
 
5828         uint8_t x86Nop = 0x90;
 
5829         for (uint32_t p=from; p < to; ++p)
 
5830                 ::pwrite(fd, &x86Nop, 1, p);
 
5834 void Writer<arm>::writeNoOps(int fd, uint32_t from, uint32_t to)
 
5836         // FIXME: need thumb nop?
 
5838         OSWriteLittleInt32(&armNop, 0, 0xe1a00000);
 
5839         for (uint32_t p=from; p < to; p += 4)
 
5840                 ::pwrite(fd, &armNop, 4, p);
 
5844 void Writer<ppc>::copyNoOps(uint8_t* from, uint8_t* to)
 
5846         for (uint8_t* p=from; p < to; p += 4)
 
5847                 OSWriteBigInt32((uint32_t*)p, 0, 0x60000000);
 
5851 void Writer<ppc64>::copyNoOps(uint8_t* from, uint8_t* to)
 
5853         for (uint8_t* p=from; p < to; p += 4)
 
5854                 OSWriteBigInt32((uint32_t*)p, 0, 0x60000000);
 
5858 void Writer<x86>::copyNoOps(uint8_t* from, uint8_t* to)
 
5860         for (uint8_t* p=from; p < to; ++p)
 
5865 void Writer<x86_64>::copyNoOps(uint8_t* from, uint8_t* to)
 
5867         for (uint8_t* p=from; p < to; ++p)
 
5872 void Writer<arm>::copyNoOps(uint8_t* from, uint8_t* to)
 
5874     // fixme: need thumb nop?
 
5875         for (uint8_t* p=from; p < to; p += 4)
 
5876                 OSWriteBigInt32((uint32_t*)p, 0, 0xe1a00000);
 
5879 static const char* stringName(const char* str)
 
5881         if ( strncmp(str, "cstring=", 8) == 0)  {
 
5882                 static char buffer[1024];
 
5885                 for(const char*s = &str[8]; *s != '\0'; ++s) {
 
5899                         if ( t > &buffer[1020] ) {
 
5918 template <> const char* Writer<ppc>::getArchString()    { return "ppc"; }
 
5919 template <> const char* Writer<ppc64>::getArchString()  { return "ppc64"; }
 
5920 template <> const char* Writer<x86>::getArchString()    { return "i386"; }
 
5921 template <> const char* Writer<x86_64>::getArchString() { return "x86_64"; }
 
5922 template <> const char* Writer<arm>::getArchString()    { return "arm"; }
 
5924 template <typename A>
 
5925 void Writer<A>::writeMap()
 
5927         if ( fOptions.generatedMapPath() != NULL ) {
 
5928                 FILE* mapFile = fopen(fOptions.generatedMapPath(), "w"); 
 
5929                 if ( mapFile != NULL ) {
 
5930                         // write output path
 
5931                         fprintf(mapFile, "# Path: %s\n", fFilePath);
 
5932                         // write output architecure
 
5933                         fprintf(mapFile, "# Arch: %s\n", getArchString());
 
5935                         if ( fUUIDAtom != NULL ) {
 
5936                                 const uint8_t* uuid = fUUIDAtom->getUUID();
 
5937                                 fprintf(mapFile, "# UUID: %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X \n",
 
5938                                         uuid[0], uuid[1], uuid[2],  uuid[3],  uuid[4],  uuid[5],  uuid[6],  uuid[7],
 
5939                                         uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
 
5941                         // write table of object files
 
5942                         std::map<ObjectFile::Reader*, uint32_t> readerToOrdinal;
 
5943                         std::map<uint32_t, ObjectFile::Reader*> ordinalToReader;
 
5944                         std::map<ObjectFile::Reader*, uint32_t> readerToFileOrdinal;
 
5945                         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
5946                                 std::vector<SectionInfo*>& sectionInfos = (*segit)->fSections;
 
5947                                 for (std::vector<SectionInfo*>::iterator secit = sectionInfos.begin(); secit != sectionInfos.end(); ++secit) {
 
5948                                         if ( ! (*secit)->fVirtualSection ) {
 
5949                                                 std::vector<ObjectFile::Atom*>& sectionAtoms = (*secit)->fAtoms;
 
5950                                                 for (std::vector<ObjectFile::Atom*>::iterator ait = sectionAtoms.begin(); ait != sectionAtoms.end(); ++ait) {
 
5951                                                         ObjectFile::Reader* reader = (*ait)->getFile();
 
5952                                                         uint32_t readerOrdinal = (*ait)->getOrdinal();
 
5953                                                         std::map<ObjectFile::Reader*, uint32_t>::iterator pos = readerToOrdinal.find(reader);
 
5954                                                         if ( pos == readerToOrdinal.end() ) {
 
5955                                                                 readerToOrdinal[reader] = readerOrdinal;
 
5956                                                                 ordinalToReader[readerOrdinal] = reader;
 
5962                         fprintf(mapFile, "# Object files:\n");
 
5963                         fprintf(mapFile, "[%3u] %s\n", 0, "linker synthesized");
 
5964                         uint32_t fileIndex = 0;
 
5965                         readerToFileOrdinal[this] = fileIndex++;
 
5966                         for(std::map<uint32_t, ObjectFile::Reader*>::iterator it = ordinalToReader.begin(); it != ordinalToReader.end(); ++it) {
 
5967                                 if ( it->first != 0 ) {
 
5968                                         fprintf(mapFile, "[%3u] %s\n", fileIndex, it->second->getPath());
 
5969                                         readerToFileOrdinal[it->second] = fileIndex++;
 
5972                         // write table of sections
 
5973                         fprintf(mapFile, "# Sections:\n");
 
5974                         fprintf(mapFile, "# Address\tSize    \tSegment\tSection\n"); 
 
5975                         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
5976                                 std::vector<SectionInfo*>& sectionInfos = (*segit)->fSections;
 
5977                                 for (std::vector<SectionInfo*>::iterator secit = sectionInfos.begin(); secit != sectionInfos.end(); ++secit) {
 
5978                                         if ( ! (*secit)->fVirtualSection ) {
 
5979                                                 SectionInfo* sect = *secit;
 
5980                                                 fprintf(mapFile, "0x%08llX\t0x%08llX\t%s\t%s\n", sect->getBaseAddress(), sect->fSize, 
 
5981                                                         (*segit)->fName, sect->fSectionName);
 
5985                         // write table of symbols
 
5986                         fprintf(mapFile, "# Symbols:\n");
 
5987                         fprintf(mapFile, "# Address\tSize    \tFile  Name\n"); 
 
5988                         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
5989                                 std::vector<SectionInfo*>& sectionInfos = (*segit)->fSections;
 
5990                                 for (std::vector<SectionInfo*>::iterator secit = sectionInfos.begin(); secit != sectionInfos.end(); ++secit) {
 
5991                                         if ( ! (*secit)->fVirtualSection ) {
 
5992                                                 std::vector<ObjectFile::Atom*>& sectionAtoms = (*secit)->fAtoms;
 
5993                                                 bool isCstring = (strcmp((*secit)->fSectionName, "__cstring") == 0);
 
5994                                                 for (std::vector<ObjectFile::Atom*>::iterator ait = sectionAtoms.begin(); ait != sectionAtoms.end(); ++ait) {
 
5995                                                         ObjectFile::Atom* atom = *ait;
 
5996                                                         fprintf(mapFile, "0x%08llX\t0x%08llX\t[%3u] %s\n", atom->getAddress(), atom->getSize(), 
 
5997                                                                 readerToFileOrdinal[atom->getFile()], isCstring ? stringName(atom->getDisplayName()): atom->getDisplayName());
 
6005                         warning("could not write map file: %s\n", fOptions.generatedMapPath());
 
6010 static const char* sCleanupFile = NULL;
 
6011 static void cleanup(int sig)
 
6013         ::signal(sig, SIG_DFL);
 
6014         if ( sCleanupFile != NULL ) {
 
6015                 ::unlink(sCleanupFile);
 
6017         if ( sig == SIGINT )
 
6022 template <typename A>
 
6023 uint64_t Writer<A>::writeAtoms()
 
6025         // for UNIX conformance, error if file exists and is not writable
 
6026         if ( (access(fFilePath, F_OK) == 0) && (access(fFilePath, W_OK) == -1) )
 
6027                 throwf("can't write output file: %s", fFilePath);
 
6029         int permissions = 0777;
 
6030         if ( fOptions.outputKind() == Options::kObjectFile )
 
6032         // Calling unlink first assures the file is gone so that open creates it with correct permissions
 
6033         // It also handles the case where fFilePath file is not writable but its directory is
 
6034         // And it means we don't have to truncate the file when done writing (in case new is smaller than old)
 
6035         (void)unlink(fFilePath);
 
6037         // try to allocate buffer for entire output file content
 
6039         SectionInfo* lastSection = fSegmentInfos.back()->fSections.back();
 
6040         uint64_t fileBufferSize = (lastSection->fFileOffset + lastSection->fSize + 4095) & (-4096);
 
6041         uint8_t* wholeBuffer = (uint8_t*)calloc(fileBufferSize, 1);
 
6042         uint8_t* atomBuffer = NULL;
 
6043         bool streaming = false;
 
6044         if ( wholeBuffer == NULL ) {
 
6045                 fd = open(fFilePath, O_CREAT | O_WRONLY | O_TRUNC, permissions);
 
6047                         throwf("can't open output file for writing: %s, errno=%d", fFilePath, errno);
 
6048                 atomBuffer = new uint8_t[(fLargestAtomSize+4095) & (-4096)];
 
6050                 // install signal handlers to delete output file if program is killed 
 
6051                 sCleanupFile = fFilePath;
 
6052                 ::signal(SIGINT, cleanup);
 
6053                 ::signal(SIGBUS, cleanup);
 
6054                 ::signal(SIGSEGV, cleanup);
 
6059                 for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
6060                         SegmentInfo* curSegment = *segit;
 
6061                         std::vector<SectionInfo*>& sectionInfos = curSegment->fSections;
 
6062                         for (std::vector<SectionInfo*>::iterator secit = sectionInfos.begin(); secit != sectionInfos.end(); ++secit) {
 
6063                                 SectionInfo* curSection = *secit;
 
6064                                 std::vector<ObjectFile::Atom*>& sectionAtoms = curSection->fAtoms;
 
6065                                 //printf("writing with max atom size 0x%X\n", fLargestAtomSize);
 
6066                                 //fprintf(stderr, "writing %lu atoms for section %p %s at file offset 0x%08llX\n", sectionAtoms.size(), curSection, curSection->fSectionName, curSection->fFileOffset);
 
6067                                 if ( ! curSection->fAllZeroFill ) {
 
6068                                         bool needsNops = ((strcmp(curSection->fSegmentName, "__TEXT") == 0) && (strncmp(curSection->fSectionName, "__text", 6) == 0));
 
6069                                         for (std::vector<ObjectFile::Atom*>::iterator ait = sectionAtoms.begin(); ait != sectionAtoms.end(); ++ait) {
 
6070                                                 ObjectFile::Atom* atom = *ait;
 
6071                                                 if ( (atom->getDefinitionKind() != ObjectFile::Atom::kExternalDefinition)
 
6072                                                   && (atom->getDefinitionKind() != ObjectFile::Atom::kExternalWeakDefinition)
 
6073                                                   && (atom->getDefinitionKind() != ObjectFile::Atom::kAbsoluteSymbol) ) {
 
6074                                                         uint32_t fileOffset = curSection->fFileOffset + atom->getSectionOffset();
 
6075                                                         if ( fileOffset != end ) {
 
6076                                                                 //fprintf(stderr, "writing %d pad bytes, needsNops=%d\n", fileOffset-end, needsNops);
 
6078                                                                         // fill gaps with no-ops
 
6080                                                                                 writeNoOps(fd, end, fileOffset);
 
6082                                                                                 copyNoOps(&wholeBuffer[end], &wholeBuffer[fileOffset]);
 
6084                                                                 else if ( streaming ) {
 
6086                                                                         if ( (fileOffset-end) == 4 ) {
 
6088                                                                                 ::pwrite(fd, &zero, 4, end);
 
6091                                                                                 uint8_t zero = 0x00;
 
6092                                                                                 for (uint32_t p=end; p < fileOffset; ++p)
 
6093                                                                                         ::pwrite(fd, &zero, 1, p);
 
6097                                                         uint64_t atomSize = atom->getSize();
 
6099                                                                 if ( atomSize > fLargestAtomSize ) 
 
6100                                                                         throwf("ld64 internal error: atom \"%s\"is larger than expected 0x%llX > 0x%X", 
 
6101                                                                                                 atom->getDisplayName(), atomSize, fLargestAtomSize);
 
6104                                                                 if ( fileOffset > fileBufferSize )
 
6105                                                                         throwf("ld64 internal error: atom \"%s\" has file offset greater thatn expceted 0x%X > 0x%llX", 
 
6106                                                                                                 atom->getDisplayName(), fileOffset, fileBufferSize);
 
6108                                                         uint8_t* buffer = streaming ? atomBuffer : &wholeBuffer[fileOffset];
 
6109                                                         end = fileOffset+atomSize;
 
6111                                                         atom->copyRawContent(buffer);
 
6112                                                         // apply any fix-ups
 
6114                                                                 std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
6115                                                                 for (std::vector<ObjectFile::Reference*>::iterator it=references.begin(); it != references.end(); it++) {
 
6116                                                                         ObjectFile::Reference* ref = *it;
 
6117                                                                         if ( fOptions.outputKind() == Options::kObjectFile ) {
 
6119                                                                                 // skip fix-ups for undefined targets
 
6120                                                                                 if ( &(ref->getTarget()) != NULL )
 
6121                                                                                         this->fixUpReferenceRelocatable(ref, atom, buffer);
 
6124                                                                                 // producing final linked image
 
6125                                                                                 this->fixUpReferenceFinal(ref, atom, buffer);
 
6129                                                         catch (const char* msg) {
 
6130                                                                 throwf("%s in %s from %s", msg, atom->getDisplayName(), atom->getFile()->getPath());
 
6132                                                         //fprintf(stderr, "writing 0x%08X -> 0x%08X (addr=0x%llX, size=0x%llX), atom %p %s from %s\n", 
 
6133                                                         //      fileOffset, end, atom->getAddress(), atom->getSize(), atom, atom->getDisplayName(), atom->getFile()->getPath());
 
6136                                                                 ::pwrite(fd, buffer, atomSize, fileOffset);
 
6139                                                                 if ( (fileOffset + atomSize) > size )
 
6140                                                                         size = fileOffset + atomSize;
 
6148                 // update content based UUID
 
6149                 if ( fOptions.getUUIDMode() == Options::kUUIDContent ) {
 
6150                         uint8_t digest[CC_MD5_DIGEST_LENGTH];
 
6152                                 // if output file file did not fit in memory, re-read file to generate md5 hash
 
6153                                 uint32_t kMD5BufferSize = 16*1024;
 
6154                                 uint8_t* md5Buffer = (uint8_t*)::malloc(kMD5BufferSize);
 
6155                                 if ( md5Buffer != NULL ) {
 
6156                                         CC_MD5_CTX md5State;
 
6157                                         CC_MD5_Init(&md5State);
 
6158                                         ::lseek(fd, 0, SEEK_SET);
 
6160                                         while ( (len = ::read(fd, md5Buffer, kMD5BufferSize)) > 0 ) 
 
6161                                                 CC_MD5_Update(&md5State, md5Buffer, len);
 
6162                                         CC_MD5_Final(digest, &md5State);
 
6166                                         // if malloc fails, fall back to random uuid
 
6167                                         ::uuid_generate_random(digest);
 
6169                                 fUUIDAtom->setContent(digest);
 
6170                                 uint32_t uuidOffset = ((SectionInfo*)fUUIDAtom->getSection())->fFileOffset + fUUIDAtom->getSectionOffset();
 
6171                                 fUUIDAtom->copyRawContent(atomBuffer);
 
6172                                 ::pwrite(fd, atomBuffer, fUUIDAtom->getSize(), uuidOffset);
 
6175                                 // if output file fit in memory, just genrate an md5 hash in memory
 
6177                                 // temp hack for building on Tiger
 
6178                                 CC_MD5_CTX md5State;
 
6179                                 CC_MD5_Init(&md5State);
 
6180                                 CC_MD5_Update(&md5State, wholeBuffer, size);
 
6181                                 CC_MD5_Final(digest, &md5State);
 
6183                                 CC_MD5(wholeBuffer, size, digest);
 
6185                                 fUUIDAtom->setContent(digest);
 
6186                                 uint32_t uuidOffset = ((SectionInfo*)fUUIDAtom->getSection())->fFileOffset + fUUIDAtom->getSectionOffset();
 
6187                                 fUUIDAtom->copyRawContent(&wholeBuffer[uuidOffset]);
 
6192                 if ( sCleanupFile != NULL ) 
 
6193                         ::unlink(sCleanupFile);
 
6199                 delete [] atomBuffer;
 
6201                 // restore default signal handlers
 
6202                 sCleanupFile = NULL;
 
6203                 ::signal(SIGINT, SIG_DFL);
 
6204                 ::signal(SIGBUS, SIG_DFL);
 
6205                 ::signal(SIGSEGV, SIG_DFL);
 
6208                 // write whole output file in one chunk
 
6209                 fd = open(fFilePath, O_CREAT | O_WRONLY | O_TRUNC, permissions);
 
6211                         throwf("can't open output file for writing: %s, errno=%d", fFilePath, errno);
 
6212                 ::pwrite(fd, wholeBuffer, size, 0);
 
6214                 delete [] wholeBuffer;
 
6221 void Writer<arm>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
6223         int64_t         displacement;
 
6225         uint32_t        instruction;
 
6226         uint32_t        newInstruction;
 
6227         uint64_t        targetAddr = 0;
 
6230         uint32_t        opcode = 0;
 
6231         bool            relocateableExternal = false;
 
6236         if ( ref->getTargetBinding() != ObjectFile::Reference::kDontBind ) {
 
6237                 targetAddr = ref->getTarget().getAddress() + ref->getTargetOffset();
 
6238                 relocateableExternal = (relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal);
 
6241         uint32_t* fixUp = (uint32_t*)&buffer[ref->getFixUpOffset()];
 
6242         switch ( (arm::ReferenceKinds)(ref->getKind()) ) {
 
6244                 case arm::kFollowOn:
 
6245                 case arm::kGroupSubordinate:
 
6248                 case arm::kPointerWeakImport:
 
6250                         // If this is the lazy pointers section, then set all lazy pointers to
 
6251                         // point to the dyld stub binding helper.
 
6252                         if ( ((SectionInfo*)inAtom->getSection())->fAllLazyPointers 
 
6253                           || ((SectionInfo*)inAtom->getSection())->fAllLazyDylibPointers ) {
 
6254                                 switch (ref->getTarget().getDefinitionKind()) {
 
6255                                         case ObjectFile::Atom::kExternalDefinition:
 
6256                                         case ObjectFile::Atom::kExternalWeakDefinition:
 
6257                                                 // prebound lazy pointer to another dylib ==> pointer contains zero
 
6258                                                 LittleEndian::set32(*fixUp, 0);
 
6260                                         case ObjectFile::Atom::kTentativeDefinition:
 
6261                                         case ObjectFile::Atom::kRegularDefinition:
 
6262                                         case ObjectFile::Atom::kWeakDefinition:
 
6263                                         case ObjectFile::Atom::kAbsoluteSymbol:
 
6264                                                 // prebound lazy pointer to withing this dylib ==> pointer contains address
 
6265                                                 if ( ref->getTarget().isThumb() && (ref->getTargetOffset() == 0) )
 
6267                                                 LittleEndian::set32(*fixUp, targetAddr);
 
6271                         else if ( relocateableExternal ) {
 
6272                                 if ( fOptions.prebind() ) {
 
6273                                         switch (ref->getTarget().getDefinitionKind()) {
 
6274                                                 case ObjectFile::Atom::kExternalDefinition:
 
6275                                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
6276                                                         // prebound external relocation ==> pointer contains addend
 
6277                                                         LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
6279                                                 case ObjectFile::Atom::kTentativeDefinition:
 
6280                                                 case ObjectFile::Atom::kRegularDefinition:
 
6281                                                 case ObjectFile::Atom::kWeakDefinition:
 
6282                                                         // prebound external relocation to internal atom ==> pointer contains target address + addend
 
6283                                                         if ( ref->getTarget().isThumb() && (ref->getTargetOffset() == 0) )
 
6285                                                         LittleEndian::set32(*fixUp, targetAddr);
 
6287                                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
6291                                 else if ( !fOptions.makeClassicDyldInfo() 
 
6292                                                                 && (ref->getTarget().getDefinitionKind() == ObjectFile::Atom::kWeakDefinition) ) {
 
6293                                         // when using only compressed dyld info, pointer is initially set to point directly to weak definition
 
6294                                         if ( ref->getTarget().isThumb() )
 
6296                                         LittleEndian::set32(*fixUp, targetAddr);
 
6299                                         // external relocation ==> pointer contains addend
 
6300                                         LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
6304                                 // pointer contains target address
 
6305                                 if ( ref->getTarget().isThumb() && (ref->getTargetOffset() == 0))
 
6307                                 LittleEndian::set32(*fixUp, targetAddr);
 
6310                 case arm::kPointerDiff:
 
6311                         LittleEndian::set32(*fixUp,
 
6312                                 (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
 
6314                 case arm::kReadOnlyPointer:
 
6315                         if ( ref->getTarget().isThumb() && (ref->getTargetOffset() == 0))
 
6317                         switch ( ref->getTarget().getDefinitionKind() ) {
 
6318                                 case ObjectFile::Atom::kRegularDefinition:
 
6319                                 case ObjectFile::Atom::kWeakDefinition:
 
6320                                 case ObjectFile::Atom::kTentativeDefinition:
 
6321                                         // pointer contains target address
 
6322                                         LittleEndian::set32(*fixUp, targetAddr);
 
6324                                 case ObjectFile::Atom::kExternalDefinition:
 
6325                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
6326                                         // external relocation ==> pointer contains addend
 
6327                                         LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
6329                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
6330                                         // pointer contains target address
 
6331                                         LittleEndian::set32(*fixUp, targetAddr);
 
6335                 case arm::kBranch24WeakImport:
 
6336                 case arm::kBranch24:
 
6337                         displacement = targetAddr - (inAtom->getAddress() + ref->getFixUpOffset());
 
6338                         // check if this is a branch to a branch island that can be skipped
 
6339                         if ( ref->getTarget().getContentType() == ObjectFile::Atom::kBranchIsland ) {
 
6340                                 uint64_t finalTargetAddress = ((BranchIslandAtom<arm>*)(&(ref->getTarget())))->getFinalTargetAdress();
 
6341                                 int64_t altDisplacment = finalTargetAddress - (inAtom->getAddress() + ref->getFixUpOffset());
 
6342                                 if ( (altDisplacment < 33554428LL) && (altDisplacment > (-33554432LL)) ) {
 
6343                                         //fprintf(stderr, "using altDisplacment = %lld\n", altDisplacment);
 
6344                                         // yes, we can skip the branch island
 
6345                                         displacement = altDisplacment;
 
6348                         // The pc added will be +8 from the pc
 
6350                         //fprintf(stderr, "bl/blx fixup to %s at 0x%08llX, displacement = 0x%08llX\n", ref->getTarget().getDisplayName(), ref->getTarget().getAddress(), displacement);
 
6351                         // max positive displacement is 0x007FFFFF << 2
 
6352                         // max negative displacement is 0xFF800000 << 2
 
6353                         if ( (displacement > 33554428LL) || (displacement < (-33554432LL)) ) {
 
6354                                 throwf("b/bl/blx out of range (%lld max is +/-32M) from 0x%08llX %s in %s to 0x%08llX %s in %s",
 
6355                                                         displacement, inAtom->getAddress(), inAtom->getDisplayName(), inAtom->getFile()->getPath(),
 
6356                                                         ref->getTarget().getAddress(), ref->getTarget().getDisplayName(), ref->getTarget().getFile()->getPath());
 
6358                         instruction = LittleEndian::get32(*fixUp);
 
6359                         // Make sure we are calling arm with bl, thumb with blx
 
6360                         is_bl = ((instruction & 0xFF000000) == 0xEB000000);
 
6361                         is_blx = ((instruction & 0xFE000000) == 0xFA000000);
 
6362                         if ( is_bl && ref->getTarget().isThumb() ) {
 
6363                                 uint32_t opcode = 0xFA000000;
 
6364                                 uint32_t disp = (uint32_t)(displacement >> 2) & 0x00FFFFFF;
 
6365                                 uint32_t h_bit = (uint32_t)(displacement << 23) & 0x01000000;
 
6366                                 newInstruction = opcode | h_bit | disp;
 
6368                         else if ( is_blx && !ref->getTarget().isThumb() ) {
 
6369                                 uint32_t opcode = 0xEB000000;
 
6370                                 uint32_t disp = (uint32_t)(displacement >> 2) & 0x00FFFFFF;
 
6371                                 newInstruction = opcode | disp;
 
6373                         else if ( !is_bl && !is_blx && ref->getTarget().isThumb() ) {
 
6374                                 throwf("don't know how to convert instruction %x referencing %s to thumb",
 
6375                                          instruction, ref->getTarget().getDisplayName());
 
6378                                 newInstruction = (instruction & 0xFF000000) | ((uint32_t)(displacement >> 2) & 0x00FFFFFF);
 
6380                         LittleEndian::set32(*fixUp, newInstruction);
 
6382                 case arm::kThumbBranch22WeakImport:
 
6383                 case arm::kThumbBranch22:
 
6384                         instruction = LittleEndian::get32(*fixUp);
 
6385                         is_bl = ((instruction & 0xD000F800) == 0xD000F000);
 
6386                         is_blx = ((instruction & 0xD000F800) == 0xC000F000);
 
6387                         targetIsThumb = ref->getTarget().isThumb();
 
6389                         // The pc added will be +4 from the pc
 
6390                         baseAddr = inAtom->getAddress() + ref->getFixUpOffset() + 4;
 
6391                         // If the target is not thumb, we will be generating a blx instruction
 
6392                         // Since blx cannot have the low bit set, set bit[1] of the target to
 
6393                         // bit[1] of the base address, so that the difference is a multiple of
 
6395                         if ( !targetIsThumb ) {
 
6396                           targetAddr &= -3ULL;
 
6397                           targetAddr |= (baseAddr & 2LL);
 
6399                         displacement = targetAddr - baseAddr;
 
6401                         // max positive displacement is 0x003FFFFE
 
6402                         // max negative displacement is 0xFFC00000
 
6403                         if ( (displacement > 4194302LL) || (displacement < (-4194304LL)) ) {
 
6404                                 // armv7 supports a larger displacement
 
6405                                 if ( fOptions.preferSubArchitecture() && fOptions.subArchitecture() == CPU_SUBTYPE_ARM_V7 ) {
 
6406                                         if ( (displacement > 16777214) || (displacement < (-16777216LL)) ) {
 
6407                                                 throwf("thumb bl/blx out of range (%lld max is +/-16M) from %s in %s to %s in %s",
 
6408                                                                 displacement, inAtom->getDisplayName(), inAtom->getFile()->getPath(),
 
6409                                                                 ref->getTarget().getDisplayName(), ref->getTarget().getFile()->getPath());
 
6412                                                 // The instruction is really two instructions:
 
6413                                                 // The lower 16 bits are the first instruction, which contains the high
 
6414                                                 //   11 bits of the displacement.
 
6415                                                 // The upper 16 bits are the second instruction, which contains the low
 
6416                                                 //   11 bits of the displacement, as well as differentiating bl and blx.
 
6417                                                 uint32_t s = (uint32_t)(displacement >> 24) & 0x1;
 
6418                                                 uint32_t i1 = (uint32_t)(displacement >> 23) & 0x1;
 
6419                                                 uint32_t i2 = (uint32_t)(displacement >> 22) & 0x1;
 
6420                                                 uint32_t imm10 = (uint32_t)(displacement >> 12) & 0x3FF;
 
6421                                                 uint32_t imm11 = (uint32_t)(displacement >> 1) & 0x7FF;
 
6422                                                 uint32_t j1 = (i1 == s);
 
6423                                                 uint32_t j2 = (i2 == s);
 
6425                                                         if ( targetIsThumb )
 
6426                                                                 opcode = 0xD000F000; // keep bl
 
6428                                                                 opcode = 0xC000F000; // change to blx
 
6430                                                 else if ( is_blx ) {
 
6431                                                         if ( targetIsThumb )
 
6432                                                                 opcode = 0xD000F000; // change to bl
 
6434                                                                 opcode = 0xC000F000; // keep blx
 
6436                                                 else if ( !is_bl && !is_blx && !targetIsThumb ) {
 
6437                                                   throwf("don't know how to convert instruction %x referencing %s to arm",
 
6438                                                                  instruction, ref->getTarget().getDisplayName());
 
6440                                                 nextDisp = (j1 << 13) | (j2 << 11) | imm11;
 
6441                                                 firstDisp = (s << 10) | imm10;
 
6442                                                 newInstruction = opcode | (nextDisp << 16) | firstDisp;
 
6443                                                 //warning("s=%d, j1=%d, j2=%d, imm10=0x%0X, imm11=0x%0X, opcode=0x%08X, first=0x%04X, next=0x%04X, new=0x%08X, disp=0x%llX for %s to %s\n",
 
6444                                                 //      s, j1, j2, imm10, imm11, opcode, firstDisp, nextDisp, newInstruction, displacement, inAtom->getDisplayName(), ref->getTarget().getDisplayName());
 
6445                                                 LittleEndian::set32(*fixUp, newInstruction);
 
6449                                         throwf("thumb bl/blx out of range (%lld max is +/-4M) from %s in %s to %s in %s",
 
6450                                                                 displacement, inAtom->getDisplayName(), inAtom->getFile()->getPath(),
 
6451                                                                 ref->getTarget().getDisplayName(), ref->getTarget().getFile()->getPath());
 
6455                                 // The instruction is really two instructions:
 
6456                                 // The lower 16 bits are the first instruction, which contains the high
 
6457                                 //   11 bits of the displacement.
 
6458                                 // The upper 16 bits are the second instruction, which contains the low
 
6459                                 //   11 bits of the displacement, as well as differentiating bl and blx.
 
6460                                 firstDisp = (uint32_t)(displacement >> 12) & 0x7FF;
 
6461                                 nextDisp = (uint32_t)(displacement >> 1) & 0x7FF;
 
6462                                 if ( is_bl && !targetIsThumb ) {
 
6463                                         opcode = 0xE800F000;
 
6465                                 else if ( is_blx && targetIsThumb ) {
 
6466                                         opcode = 0xF800F000;
 
6468                                 else if ( !is_bl && !is_blx && !targetIsThumb ) {
 
6469                                   throwf("don't know how to convert instruction %x referencing %s to arm",
 
6470                                                  instruction, ref->getTarget().getDisplayName());
 
6473                                         opcode = instruction & 0xF800F800;
 
6475                                 newInstruction = opcode | (nextDisp << 16) | firstDisp;
 
6476                                 LittleEndian::set32(*fixUp, newInstruction);
 
6479                 case arm::kDtraceProbeSite:
 
6480                         if ( inAtom->isThumb() ) {
 
6481                                 // change 32-bit blx call site to two thumb NOPs
 
6482                                 LittleEndian::set32(*fixUp, 0x46C046C0);
 
6485                                 // change call site to a NOP
 
6486                                 LittleEndian::set32(*fixUp, 0xE1A00000);
 
6489                 case arm::kDtraceIsEnabledSite:
 
6490                         if ( inAtom->isThumb() ) {
 
6491                                 // change 32-bit blx call site to 'nop', 'eor r0, r0'
 
6492                                 LittleEndian::set32(*fixUp, 0x46C04040);
 
6495                                 // change call site to 'eor r0, r0, r0'
 
6496                                 LittleEndian::set32(*fixUp, 0xE0200000);
 
6499                 case arm::kDtraceTypeReference:
 
6500                 case arm::kDtraceProbe:
 
6501                         // nothing to fix up
 
6503                 case arm::kPointerDiff12:
 
6504                         displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
6505                         if ( (displacement > 4092LL) || (displacement <-4092LL) ) {
 
6506                                 throwf("ldr 12-bit displacement out of range (%lld max +/-4096) in %s", displacement, inAtom->getDisplayName());
 
6508                         instruction = LittleEndian::get32(*fixUp);
 
6509                         if ( displacement >= 0 ) {
 
6510                                 instruction &= 0xFFFFF000;
 
6511                                 instruction |= ((uint32_t)displacement & 0xFFF);
 
6514                                 instruction &= 0xFF7FF000;
 
6515                                 instruction |= ((uint32_t)(-displacement) & 0xFFF);
 
6517                         LittleEndian::set32(*fixUp, instruction);
 
6523 void Writer<arm>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
6525         int64_t         displacement;
 
6526         uint32_t        instruction;
 
6527         uint32_t        newInstruction;
 
6528         uint64_t        targetAddr = 0;
 
6532         uint32_t        opcode = 0;
 
6533         bool            relocateableExternal = false;
 
6538         if ( ref->getTargetBinding() != ObjectFile::Reference::kDontBind ) {
 
6539                 targetAddr = ref->getTarget().getAddress() + ref->getTargetOffset();
 
6540                 relocateableExternal = this->makesExternalRelocatableReference(ref->getTarget());       
 
6543         uint32_t* fixUp = (uint32_t*)&buffer[ref->getFixUpOffset()];
 
6544         switch ( (arm::ReferenceKinds)(ref->getKind()) ) {
 
6546                 case arm::kFollowOn:
 
6547                 case arm::kGroupSubordinate:
 
6551                 case arm::kReadOnlyPointer:
 
6552                 case arm::kPointerWeakImport:
 
6554                         if ( ((SectionInfo*)inAtom->getSection())->fAllNonLazyPointers ) {
 
6555                                 // indirect symbol table has INDIRECT_SYMBOL_LOCAL, so we must put address in content
 
6556                                 if ( this->indirectSymbolInRelocatableIsLocal(ref) ) 
 
6557                                         LittleEndian::set32(*fixUp, targetAddr);
 
6559                                         LittleEndian::set32(*fixUp, 0);
 
6561                         else if ( relocateableExternal ) {
 
6562                                 if ( fOptions.prebind() ) {
 
6563                                         switch (ref->getTarget().getDefinitionKind()) {
 
6564                                                 case ObjectFile::Atom::kExternalDefinition:
 
6565                                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
6566                                                         // prebound external relocation ==> pointer contains addend
 
6567                                                         LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
6569                                                 case ObjectFile::Atom::kTentativeDefinition:
 
6570                                                 case ObjectFile::Atom::kRegularDefinition:
 
6571                                                 case ObjectFile::Atom::kWeakDefinition:
 
6572                                                         // prebound external relocation to internal atom ==> pointer contains target address + addend
 
6573                                                         LittleEndian::set32(*fixUp, targetAddr);
 
6575                                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
6581                                 // internal relocation
 
6582                                 if ( ref->getTarget().getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition ) {
 
6583                                         // pointer contains target address
 
6584                                         if ( ref->getTarget().isThumb() && (ref->getTargetOffset() == 0))
 
6586                                                 LittleEndian::set32(*fixUp, targetAddr);
 
6589                                                 // pointer contains addend
 
6590                                                 LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
6595                 case arm::kPointerDiff:
 
6596                                 LittleEndian::set32(*fixUp,
 
6597                                         (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
 
6599                 case arm::kDtraceProbeSite:
 
6600                 case arm::kDtraceIsEnabledSite:
 
6601                 case arm::kBranch24WeakImport:
 
6602                 case arm::kBranch24:
 
6603                         displacement = targetAddr - (inAtom->getAddress() + ref->getFixUpOffset());
 
6604                         // The pc added will be +8 from the pc
 
6606                         // fprintf(stderr, "b/bl/blx fixup to %s at 0x%08llX, displacement = 0x%08llX\n", ref->getTarget().getDisplayName(), ref->getTarget().getAddress(), displacement);
 
6607                         if ( relocateableExternal )  {
 
6608                                 // doing "ld -r" to an external symbol
 
6609                                 // the mach-o way of encoding this is that the bl instruction's target addr is the offset into the target
 
6610                                 displacement -= ref->getTarget().getAddress();
 
6613                                 // max positive displacement is 0x007FFFFF << 2
 
6614                                 // max negative displacement is 0xFF800000 << 2
 
6615                                 if ( (displacement > 33554428LL) || (displacement < (-33554432LL)) ) {
 
6616                                         throwf("arm b/bl/blx out of range (%lld max is +/-32M) from %s in %s to %s in %s",
 
6617                                                         displacement, inAtom->getDisplayName(), inAtom->getFile()->getPath(),
 
6618                                                         ref->getTarget().getDisplayName(), ref->getTarget().getFile()->getPath());
 
6621                         instruction = LittleEndian::get32(*fixUp);
 
6622                         // Make sure we are calling arm with bl, thumb with blx
 
6623                         is_bl = ((instruction & 0xFF000000) == 0xEB000000);
 
6624                         is_blx = ((instruction & 0xFE000000) == 0xFA000000);
 
6625                         if ( is_bl && ref->getTarget().isThumb() ) {
 
6626                                 uint32_t opcode = 0xFA000000;
 
6627                                 uint32_t disp = (uint32_t)(displacement >> 2) & 0x00FFFFFF;
 
6628                                 uint32_t h_bit = (uint32_t)(displacement << 23) & 0x01000000;
 
6629                                 newInstruction = opcode | h_bit | disp;
 
6631                         else if ( is_blx && !ref->getTarget().isThumb() ) {
 
6632                                 uint32_t opcode = 0xEB000000;
 
6633                                 uint32_t disp = (uint32_t)(displacement >> 2) & 0x00FFFFFF;
 
6634                                 newInstruction = opcode | disp;
 
6636                         else if ( !is_bl && !is_blx && ref->getTarget().isThumb() ) {
 
6637                                 throwf("don't know how to convert instruction %x referencing %s to thumb",
 
6638                                          instruction, ref->getTarget().getDisplayName());
 
6641                                 newInstruction = (instruction & 0xFF000000) | ((uint32_t)(displacement >> 2) & 0x00FFFFFF);
 
6643                         LittleEndian::set32(*fixUp, newInstruction);
 
6645                 case arm::kThumbBranch22WeakImport:
 
6646                 case arm::kThumbBranch22:
 
6647                         instruction = LittleEndian::get32(*fixUp);
 
6648                         is_bl = ((instruction & 0xF8000000) == 0xF8000000);
 
6649                         is_blx = ((instruction & 0xF8000000) == 0xE8000000);
 
6650                         targetIsThumb = ref->getTarget().isThumb();
 
6652                         // The pc added will be +4 from the pc
 
6653                         baseAddr = inAtom->getAddress() + ref->getFixUpOffset() + 4;
 
6654                         // If the target is not thumb, we will be generating a blx instruction
 
6655                         // Since blx cannot have the low bit set, set bit[1] of the target to
 
6656                         // bit[1] of the base address, so that the difference is a multiple of
 
6658                         if (!targetIsThumb) {
 
6659                                 targetAddr &= -3ULL;
 
6660                                 targetAddr |= (baseAddr & 2LL);
 
6662                         displacement = targetAddr - baseAddr;
 
6664                         //fprintf(stderr, "thumb %s fixup to %s at 0x%08llX, baseAddr = 0x%08llX, displacement = 0x%08llX, %d\n", is_blx ? "blx" : "bl",  ref->getTarget().getDisplayName(), targetAddr, baseAddr, displacement, targetIsThumb);
 
6665                         if ( relocateableExternal )  {
 
6666                                 // doing "ld -r" to an external symbol
 
6667                                 // the mach-o way of encoding this is that the bl instruction's target addr is the offset into the target
 
6668                                 displacement -= ref->getTarget().getAddress();
 
6671                         if ( (displacement > 4194302LL) || (displacement < (-4194304LL)) ) {
 
6672                                 // armv7 supports a larger displacement
 
6673                                 if ( fOptions.preferSubArchitecture() && fOptions.subArchitecture() == CPU_SUBTYPE_ARM_V7 ) {
 
6674                                         if ( (displacement > 16777214) || (displacement < (-16777216LL)) ) {
 
6675                                                 throwf("thumb bl/blx out of range (%lld max is +/-16M) from %s in %s to %s in %s",
 
6676                                                                 displacement, inAtom->getDisplayName(), inAtom->getFile()->getPath(),
 
6677                                                                 ref->getTarget().getDisplayName(), ref->getTarget().getFile()->getPath());
 
6680                                                 // The instruction is really two instructions:
 
6681                                                 // The lower 16 bits are the first instruction, which contains the high
 
6682                                                 //   11 bits of the displacement.
 
6683                                                 // The upper 16 bits are the second instruction, which contains the low
 
6684                                                 //   11 bits of the displacement, as well as differentiating bl and blx.
 
6685                                                 uint32_t s = (uint32_t)(displacement >> 24) & 0x1;
 
6686                                                 uint32_t i1 = (uint32_t)(displacement >> 23) & 0x1;
 
6687                                                 uint32_t i2 = (uint32_t)(displacement >> 22) & 0x1;
 
6688                                                 uint32_t imm10 = (uint32_t)(displacement >> 12) & 0x3FF;
 
6689                                                 uint32_t imm11 = (uint32_t)(displacement >> 1) & 0x7FF;
 
6690                                                 uint32_t j1 = (i1 == s);
 
6691                                                 uint32_t j2 = (i2 == s);
 
6693                                                         if ( targetIsThumb )
 
6694                                                                 opcode = 0xD000F000; // keep bl
 
6696                                                                 opcode = 0xC000F000; // change to blx
 
6698                                                 else if ( is_blx ) {
 
6699                                                         if ( targetIsThumb )
 
6700                                                                 opcode = 0xD000F000; // change to bl
 
6702                                                                 opcode = 0xC000F000; // keep blx
 
6704                                                 else if ( !is_bl && !is_blx && !targetIsThumb ) {
 
6705                                                   throwf("don't know how to convert instruction %x referencing %s to arm",
 
6706                                                                  instruction, ref->getTarget().getDisplayName());
 
6708                                                 nextDisp = (j1 << 13) | (j2 << 11) | imm11;
 
6709                                                 firstDisp = (s << 10) | imm10;
 
6710                                                 newInstruction = opcode | (nextDisp << 16) | firstDisp;
 
6711                                                 //warning("s=%d, j1=%d, j2=%d, imm10=0x%0X, imm11=0x%0X, opcode=0x%08X, first=0x%04X, next=0x%04X, new=0x%08X, disp=0x%llX for %s to %s\n",
 
6712                                                 //      s, j1, j2, imm10, imm11, opcode, firstDisp, nextDisp, newInstruction, displacement, inAtom->getDisplayName(), ref->getTarget().getDisplayName());
 
6713                                                 LittleEndian::set32(*fixUp, newInstruction);
 
6718                                         throwf("thumb bl/blx out of range (%lld max is +/-4M) from %s in %s to %s in %s",
 
6719                                                                 displacement, inAtom->getDisplayName(), inAtom->getFile()->getPath(),
 
6720                                                                 ref->getTarget().getDisplayName(), ref->getTarget().getFile()->getPath());
 
6723                         // The instruction is really two instructions:
 
6724                         // The lower 16 bits are the first instruction, which contains the first
 
6725                         //   11 bits of the displacement.
 
6726                         // The upper 16 bits are the second instruction, which contains the next
 
6727                         //   11 bits of the displacement, as well as differentiating bl and blx.
 
6728                         firstDisp = (uint32_t)(displacement >> 12) & 0x7FF;
 
6729                         nextDisp = (uint32_t)(displacement >> 1) & 0x7FF;
 
6730                         if ( is_bl && !targetIsThumb ) {
 
6731                                 opcode = 0xE800F000;
 
6733                         else if ( is_blx && targetIsThumb ) {
 
6734                                 opcode = 0xF800F000;
 
6736                         else if ( !is_bl && !is_blx && !targetIsThumb ) {
 
6737                                 throwf("don't know how to convert instruction %x referencing %s to arm",
 
6738                                          instruction, ref->getTarget().getDisplayName());
 
6741                                 opcode = instruction & 0xF800F800;
 
6743                         newInstruction = opcode | (nextDisp << 16) | firstDisp;
 
6744                         LittleEndian::set32(*fixUp, newInstruction);
 
6746                 case arm::kDtraceProbe:
 
6747                 case arm::kDtraceTypeReference:
 
6748                         // nothing to fix up
 
6750                 case arm::kPointerDiff12:
 
6751                         throw "internal error.  no reloc for 12-bit pointer diffs";
 
6756 void Writer<x86>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
6758         uint32_t* fixUp = (uint32_t*)&buffer[ref->getFixUpOffset()];
 
6759         uint8_t*  dtraceProbeSite;
 
6760         const int64_t kTwoGigLimit = 0x7FFFFFFF;
 
6761         const int64_t kSixteenMegLimit = 0x00FFFFFF;
 
6762         const int64_t kSixtyFourKiloLimit = 0x7FFF;
 
6763         const int64_t kOneTwentyEightLimit = 0x7F;
 
6764         int64_t displacement;
 
6766         x86::ReferenceKinds kind = (x86::ReferenceKinds)(ref->getKind());
 
6769                 case x86::kFollowOn:
 
6770                 case x86::kGroupSubordinate:
 
6773                 case x86::kPointerWeakImport:
 
6776                                 if ( this->relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal ) {
 
6777                                         if ( fOptions.prebind() ) {
 
6778                                                 switch (ref->getTarget().getDefinitionKind()) {
 
6779                                                         case ObjectFile::Atom::kExternalDefinition:
 
6780                                                         case ObjectFile::Atom::kExternalWeakDefinition:
 
6781                                                                 // prebound external relocation ==> pointer contains addend
 
6782                                                                 LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
6784                                                         case ObjectFile::Atom::kTentativeDefinition:
 
6785                                                         case ObjectFile::Atom::kRegularDefinition:
 
6786                                                         case ObjectFile::Atom::kWeakDefinition:
 
6787                                                                 // prebound external relocation to internal atom ==> pointer contains target address + addend
 
6788                                                                 LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
6790                                                         case ObjectFile::Atom::kAbsoluteSymbol:
 
6794                                         else if ( !fOptions.makeClassicDyldInfo() 
 
6795                                                                         && (ref->getTarget().getDefinitionKind() == ObjectFile::Atom::kWeakDefinition) ) {
 
6796                                                 // when using only compressed dyld info, pointer is initially set to point directly to weak definition
 
6797                                                 LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
6800                                                 // external relocation ==> pointer contains addend
 
6801                                                 LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
6805                                         // pointer contains target address
 
6806                                         //printf("Atom::fixUpReferenceFinal() target.name=%s, target.address=0x%08llX\n", target.getDisplayName(), target.getAddress());
 
6807                                         LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
6811                 case x86::kPointerDiff:
 
6812                         displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
6813                         LittleEndian::set32(*fixUp, (uint32_t)displacement);
 
6815                 case x86::kPointerDiff16:
 
6816                         displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
6817                         if ( (displacement > kSixtyFourKiloLimit) || (displacement < -(kSixtyFourKiloLimit)) ) 
 
6818                                 throwf("16-bit pointer diff out of range in %s", inAtom->getDisplayName());
 
6819                         LittleEndian::set16(*((uint16_t*)fixUp), (uint16_t)displacement);
 
6821                 case x86::kPointerDiff24:
 
6822                         displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
6823                         if ( (displacement > kSixteenMegLimit) || (displacement < 0) ) 
 
6824                                 throwf("24-bit pointer diff out of range in %s", inAtom->getDisplayName());
 
6825                         temp = LittleEndian::get32(*fixUp);
 
6827                         temp |= (displacement & 0x00FFFFFF);
 
6828                         LittleEndian::set32(*fixUp, temp);
 
6830                 case x86::kSectionOffset24:
 
6831                         displacement = ref->getTarget().getSectionOffset();
 
6832                         if ( (displacement > kSixteenMegLimit) || (displacement < 0) ) 
 
6833                                 throwf("24-bit pointer diff out of range in %s", inAtom->getDisplayName());
 
6834                         temp = LittleEndian::get32(*fixUp);
 
6836                         temp |= (displacement & 0x00FFFFFF);
 
6837                         LittleEndian::set32(*fixUp, temp);
 
6839                 case x86::kDtraceProbeSite:
 
6840                         // change call site to a NOP
 
6841                         dtraceProbeSite = (uint8_t*)fixUp;
 
6842                         dtraceProbeSite[-1] = 0x90;     // 1-byte nop
 
6843                         dtraceProbeSite[0] = 0x0F;      // 4-byte nop 
 
6844                         dtraceProbeSite[1] = 0x1F;
 
6845                         dtraceProbeSite[2] = 0x40;
 
6846                         dtraceProbeSite[3] = 0x00;
 
6848                 case x86::kDtraceIsEnabledSite:
 
6849                         // change call site to a clear eax
 
6850                         dtraceProbeSite = (uint8_t*)fixUp;
 
6851                         dtraceProbeSite[-1] = 0x33;             // xorl eax,eax
 
6852                         dtraceProbeSite[0] = 0xC0;
 
6853                         dtraceProbeSite[1] = 0x90;              // 1-byte nop
 
6854                         dtraceProbeSite[2] = 0x90;              // 1-byte nop
 
6855                         dtraceProbeSite[3] = 0x90;              // 1-byte nop
 
6857                 case x86::kPCRel32WeakImport:
 
6862                         switch ( ref->getTarget().getDefinitionKind() ) {
 
6863                                 case ObjectFile::Atom::kRegularDefinition:
 
6864                                 case ObjectFile::Atom::kWeakDefinition:
 
6865                                         displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
6867                                 case ObjectFile::Atom::kExternalDefinition:
 
6868                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
6869                                         throw "codegen problem, can't use rel32 to external symbol";
 
6870                                 case ObjectFile::Atom::kTentativeDefinition:
 
6873                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
6874                                         displacement = (ref->getTarget().getSectionOffset() + ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
6877                         if ( kind == x86::kPCRel8 ) {
 
6879                                 if ( (displacement > kOneTwentyEightLimit) || (displacement < -(kOneTwentyEightLimit)) ) {
 
6880                                         //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
 
6881                                         throwf("rel8 out of range in %s", inAtom->getDisplayName());
 
6883                                 *(int8_t*)fixUp = (int8_t)displacement;
 
6885                         else if ( kind == x86::kPCRel16 ) {
 
6887                                 if ( (displacement > kSixtyFourKiloLimit) || (displacement < -(kSixtyFourKiloLimit)) ) {
 
6888                                         //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
 
6889                                         throwf("rel16 out of range in %s", inAtom->getDisplayName());
 
6891                                 LittleEndian::set16(*((uint16_t*)fixUp), (uint16_t)displacement);
 
6894                                 if ( (displacement > kTwoGigLimit) || (displacement < (-kTwoGigLimit)) ) {
 
6895                                         //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
 
6896                                         throwf("rel32 out of range in %s", inAtom->getDisplayName());
 
6898                                 LittleEndian::set32(*fixUp, (int32_t)displacement);
 
6901                 case x86::kAbsolute32:
 
6902                         switch ( ref->getTarget().getDefinitionKind() ) {
 
6903                                 case ObjectFile::Atom::kRegularDefinition:
 
6904                                 case ObjectFile::Atom::kWeakDefinition:
 
6905                                 case ObjectFile::Atom::kTentativeDefinition:
 
6906                                         // pointer contains target address
 
6907                                         LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
6909                                 case ObjectFile::Atom::kExternalDefinition:
 
6910                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
6911                                         // external relocation ==> pointer contains addend
 
6912                                         LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
6914                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
6915                                         // pointer contains target address
 
6916                                         LittleEndian::set32(*fixUp, ref->getTarget().getSectionOffset() + ref->getTargetOffset());
 
6920                 case x86::kImageOffset32:
 
6921                         // offset of target atom from mach_header
 
6922                         displacement = ref->getTarget().getAddress() + ref->getTargetOffset() - fMachHeaderAtom->getAddress();
 
6923                         LittleEndian::set32(*fixUp, (int32_t)displacement);
 
6925                 case x86::kDtraceTypeReference:
 
6926                 case x86::kDtraceProbe:
 
6927                         // nothing to fix up
 
6935 void Writer<x86>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
6937         const int64_t kTwoGigLimit = 0x7FFFFFFF;
 
6938         const int64_t kSixtyFourKiloLimit = 0x7FFF;
 
6939         const int64_t kOneTwentyEightLimit = 0x7F;
 
6940         uint32_t* fixUp = (uint32_t*)&buffer[ref->getFixUpOffset()];
 
6941         bool isExtern = this->makesExternalRelocatableReference(ref->getTarget());      
 
6942         int64_t displacement;
 
6943         x86::ReferenceKinds kind = (x86::ReferenceKinds)(ref->getKind());
 
6946                 case x86::kFollowOn:
 
6947                 case x86::kGroupSubordinate:
 
6951                 case x86::kPointerWeakImport:
 
6952                 case x86::kAbsolute32:
 
6954                                 if ( ((SectionInfo*)inAtom->getSection())->fAllNonLazyPointers ) {
 
6955                                         // if INDIRECT_SYMBOL_LOCAL the content is pointer, else it is zero
 
6956                                         if ( this->indirectSymbolInRelocatableIsLocal(ref) ) 
 
6957                                                 LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
6959                                                 LittleEndian::set32(*fixUp, 0);
 
6961                                 else if ( isExtern ) {
 
6962                                         // external relocation ==> pointer contains addend
 
6963                                         LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
6965                                 else if ( ref->getTarget().getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition ) {
 
6966                                         // internal relocation => pointer contains target address
 
6967                                         LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
6970                                         // internal relocation to tentative ==> pointer contains addend
 
6971                                         LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
6975                 case x86::kPointerDiff:
 
6976                                 displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
6977                                 LittleEndian::set32(*fixUp, (uint32_t)displacement);
 
6979                 case x86::kPointerDiff16:
 
6980                                 displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
6981                                 if ( (displacement > kSixtyFourKiloLimit) || (displacement < -(kSixtyFourKiloLimit)) ) 
 
6982                                         throwf("16-bit pointer diff out of range in %s", inAtom->getDisplayName());
 
6983                                 LittleEndian::set16(*((uint16_t*)fixUp), (uint16_t)displacement);
 
6988                 case x86::kPCRel32WeakImport:
 
6989                 case x86::kDtraceProbeSite:
 
6990                 case x86::kDtraceIsEnabledSite:
 
6993                                         displacement = ref->getTargetOffset() - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
6995                                         displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
6996                                 if ( kind == x86::kPCRel8 ) {
 
6998                                         if ( (displacement > kOneTwentyEightLimit) || (displacement < -(kOneTwentyEightLimit)) ) {
 
6999                                                 //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
 
7000                                                 throwf("rel8 out of range (%lld)in %s", displacement, inAtom->getDisplayName());
 
7002                                         int8_t byte = (int8_t)displacement;
 
7003                                         *((int8_t*)fixUp) = byte;
 
7005                                 else if ( kind == x86::kPCRel16 ) {
 
7007                                         if ( (displacement > kSixtyFourKiloLimit) || (displacement < -(kSixtyFourKiloLimit)) ) {
 
7008                                                 //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
 
7009                                                 throwf("rel16 out of range in %s", inAtom->getDisplayName());
 
7011                                         int16_t word = (int16_t)displacement;
 
7012                                         LittleEndian::set16(*((uint16_t*)fixUp), word);
 
7015                                         if ( (displacement > kTwoGigLimit) || (displacement < (-kTwoGigLimit)) ) {
 
7016                                                 //fprintf(stderr, "call out of range, displacement=ox%llX, from %s in %s to %s in %s\n", displacement, 
 
7017                                                 //      inAtom->getDisplayName(), inAtom->getFile()->getPath(), ref->getTarget().getDisplayName(), ref->getTarget().getFile()->getPath());
 
7018                                                 throwf("rel32 out of range in %s", inAtom->getDisplayName());
 
7020                                         LittleEndian::set32(*fixUp, (int32_t)displacement);
 
7024                 case x86::kPointerDiff24:
 
7025                         throw "internal linker error, kPointerDiff24 can't be encoded into object files";
 
7026                 case x86::kImageOffset32:
 
7027                         throw "internal linker error, kImageOffset32 can't be encoded into object files";
 
7028                 case x86::kSectionOffset24:
 
7029                         throw "internal linker error, kSectionOffset24 can't be encoded into object files";
 
7030                 case x86::kDtraceProbe:
 
7031                 case x86::kDtraceTypeReference:
 
7032                         // nothing to fix up
 
7038 void Writer<x86_64>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
7040         const int64_t twoGigLimit               = 0x7FFFFFFF;
 
7041         const int64_t kSixteenMegLimit  = 0x00FFFFFF;
 
7042         uint64_t* fixUp = (uint64_t*)&buffer[ref->getFixUpOffset()];
 
7043         uint8_t*  dtraceProbeSite;
 
7044         int64_t displacement = 0;
 
7046         switch ( (x86_64::ReferenceKinds)(ref->getKind()) ) {
 
7047                 case x86_64::kNoFixUp:
 
7048                 case x86_64::kGOTNoFixUp:
 
7049                 case x86_64::kFollowOn:
 
7050                 case x86_64::kGroupSubordinate:
 
7053                 case x86_64::kPointerWeakImport:
 
7054                 case x86_64::kPointer:
 
7056                                 if ( &ref->getTarget() != NULL ) {
 
7057                                         //fprintf(stderr, "fixUpReferenceFinal: %s reference to %s\n", this->getDisplayName(), target.getDisplayName());
 
7058                                         if ( this->relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal) {
 
7059                                                 if ( !fOptions.makeClassicDyldInfo() 
 
7060                                                                         && (ref->getTarget().getDefinitionKind() == ObjectFile::Atom::kWeakDefinition) ) {
 
7061                                                         // when using only compressed dyld info, pointer is initially set to point directly to weak definition
 
7062                                                         LittleEndian::set64(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
7065                                                         // external relocation ==> pointer contains addend
 
7066                                                         LittleEndian::set64(*fixUp, ref->getTargetOffset());
 
7070                                                 // internal relocation
 
7071                                                 // pointer contains target address
 
7072                                                 //printf("Atom::fixUpReferenceFinal) target.name=%s, target.address=0x%08llX\n", target.getDisplayName(), target.getAddress());
 
7073                                                 LittleEndian::set64(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
7078                 case x86_64::kPointer32:
 
7080                                 //fprintf(stderr, "fixUpReferenceFinal: %s reference to %s\n", this->getDisplayName(), target.getDisplayName());
 
7081                                 if ( this->relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal ) {
 
7082                                         // external relocation
 
7083                                         throwf("32-bit pointer to dylib or weak symbol %s not supported for x86_64",ref->getTarget().getDisplayName());
 
7086                                         // internal relocation
 
7087                                         // pointer contains target address
 
7088                                         //printf("Atom::fixUpReferenceFinal) target.name=%s, target.address=0x%08llX\n", target.getDisplayName(), target.getAddress());
 
7089                                         displacement = ref->getTarget().getAddress() + ref->getTargetOffset();
 
7090                                         switch ( fOptions.outputKind() ) {
 
7091                                                 case Options::kObjectFile:
 
7092                                                 case Options::kPreload:
 
7093                                                 case Options::kDyld:
 
7094                                                 case Options::kDynamicLibrary:
 
7095                                                 case Options::kDynamicBundle:
 
7096                                                 case Options::kKextBundle:
 
7097                                                         throwf("32-bit pointer to symbol %s not supported for x86_64",ref->getTarget().getDisplayName());
 
7098                                                 case Options::kDynamicExecutable:
 
7099                                                         // <rdar://problem/5855588> allow x86_64 main executables to use 32-bit pointers if program loads in load 2GB
 
7100                                                         if ( (displacement > twoGigLimit) || (displacement < (-twoGigLimit)) )
 
7101                                                                 throw "32-bit pointer out of range";
 
7103                                                 case Options::kStaticExecutable:
 
7104                                                         // <rdar://problem/5855588> allow x86_64 mach_kernel to truncate pointers
 
7107                                         LittleEndian::set32(*((uint32_t*)fixUp), (uint32_t)displacement);
 
7111                 case x86_64::kPointerDiff32:
 
7112                         displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
7113                         if ( (displacement > twoGigLimit) || (displacement < (-twoGigLimit)) )
 
7114                                 throw "32-bit pointer difference out of range";
 
7115                         LittleEndian::set32(*((uint32_t*)fixUp), (uint32_t)displacement);
 
7117                 case x86_64::kPointerDiff:
 
7118                         LittleEndian::set64(*fixUp,
 
7119                                 (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
 
7121                 case x86_64::kPointerDiff24:
 
7122                         displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
7123                         if ( (displacement > kSixteenMegLimit) || (displacement < 0) ) 
 
7124                                 throwf("24-bit pointer diff out of range in %s", inAtom->getDisplayName());
 
7125                         temp = LittleEndian::get32(*((uint32_t*)fixUp));
 
7127                         temp |= (displacement & 0x00FFFFFF);
 
7128                         LittleEndian::set32(*((uint32_t*)fixUp), temp);
 
7130                 case x86_64::kSectionOffset24:
 
7131                         displacement = ref->getTarget().getSectionOffset();
 
7132                         if ( (displacement > kSixteenMegLimit) || (displacement < 0) ) 
 
7133                                 throwf("24-bit pointer diff out of range in %s", inAtom->getDisplayName());
 
7134                         temp = LittleEndian::get32(*((uint32_t*)fixUp));
 
7136                         temp |= (displacement & 0x00FFFFFF);
 
7137                         LittleEndian::set32(*((uint32_t*)fixUp), temp);
 
7139                 case x86_64::kPCRel32GOTLoad:
 
7140                 case x86_64::kPCRel32GOTLoadWeakImport:
 
7141                         // if GOT entry was optimized away, change movq instruction to a leaq
 
7142                         if ( std::find(fAllSynthesizedNonLazyPointers.begin(), fAllSynthesizedNonLazyPointers.end(), &(ref->getTarget())) == fAllSynthesizedNonLazyPointers.end() ) {
 
7143                                 //fprintf(stderr, "GOT for %s optimized away\n", ref->getTarget().getDisplayName());
 
7144                                 uint8_t* opcodes = (uint8_t*)fixUp;
 
7145                                 if ( opcodes[-2] != 0x8B )
 
7146                                         throw "GOT load reloc does not point to a movq instruction";
 
7149                         // fall into general rel32 case
 
7150                 case x86_64::kBranchPCRel32WeakImport:
 
7151                 case x86_64::kBranchPCRel32:
 
7152                 case x86_64::kBranchPCRel8:
 
7153                 case x86_64::kPCRel32:
 
7154                 case x86_64::kPCRel32_1:
 
7155                 case x86_64::kPCRel32_2:
 
7156                 case x86_64::kPCRel32_4:
 
7157                 case x86_64::kPCRel32GOT:
 
7158                 case x86_64::kPCRel32GOTWeakImport:
 
7159                         switch ( ref->getTarget().getDefinitionKind() ) {
 
7160                                 case ObjectFile::Atom::kRegularDefinition:
 
7161                                 case ObjectFile::Atom::kWeakDefinition:
 
7162                                 case ObjectFile::Atom::kTentativeDefinition:
 
7163                                         displacement = (ref->getTarget().getAddress() + (int32_t)ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
7165                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
7166                                         displacement = (ref->getTarget().getSectionOffset() + (int32_t)ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
7168                                 case ObjectFile::Atom::kExternalDefinition:
 
7169                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
7170                                         if ( fOptions.outputKind() == Options::kKextBundle )
 
7173                                                 throwf("codegen problem, can't use rel32 to external symbol %s", ref->getTarget().getDisplayName());
 
7176                         switch ( ref->getKind() ) {
 
7177                                 case x86_64::kPCRel32_1:
 
7180                                 case x86_64::kPCRel32_2:
 
7183                                 case x86_64::kPCRel32_4:
 
7186                                 case x86_64::kBranchPCRel8:
 
7190                         if ( ref->getKind() == x86_64::kBranchPCRel8 ) {
 
7191                                 if ( (displacement > 127) || (displacement < (-128)) ) {
 
7192                                         fprintf(stderr, "branch out of range from %s (%llX) in %s to %s (%llX) in %s\n", 
 
7193                                                 inAtom->getDisplayName(), inAtom->getAddress(), inAtom->getFile()->getPath(), ref->getTarget().getDisplayName(), ref->getTarget().getAddress(), ref->getTarget().getFile()->getPath());
 
7194                                         throw "rel8 out of range";
 
7196                                 *((int8_t*)fixUp) = (int8_t)displacement;
 
7199                                 if ( (displacement > twoGigLimit) || (displacement < (-twoGigLimit)) ) {
 
7200                                         fprintf(stderr, "reference out of range from %s (%llX) in %s to %s (%llX) in %s\n", 
 
7201                                                 inAtom->getDisplayName(), inAtom->getAddress(), inAtom->getFile()->getPath(), ref->getTarget().getDisplayName(), ref->getTarget().getAddress(), ref->getTarget().getFile()->getPath());
 
7202                                         throw "rel32 out of range";
 
7204                                 LittleEndian::set32(*((uint32_t*)fixUp), (int32_t)displacement);
 
7207                 case x86_64::kImageOffset32:
 
7208                         // offset of target atom from mach_header
 
7209                         displacement = ref->getTarget().getAddress() + ref->getTargetOffset() - fMachHeaderAtom->getAddress();
 
7210                         LittleEndian::set32(*((uint32_t*)fixUp), (int32_t)displacement);
 
7212                 case x86_64::kDtraceProbeSite:
 
7213                         // change call site to a NOP
 
7214                         dtraceProbeSite = (uint8_t*)fixUp;
 
7215                         dtraceProbeSite[-1] = 0x90;     // 1-byte nop
 
7216                         dtraceProbeSite[0] = 0x0F;      // 4-byte nop 
 
7217                         dtraceProbeSite[1] = 0x1F;
 
7218                         dtraceProbeSite[2] = 0x40;
 
7219                         dtraceProbeSite[3] = 0x00;
 
7221                 case x86_64::kDtraceIsEnabledSite:
 
7222                         // change call site to a clear eax
 
7223                         dtraceProbeSite = (uint8_t*)fixUp;
 
7224                         dtraceProbeSite[-1] = 0x48;             // xorq eax,eax
 
7225                         dtraceProbeSite[0] = 0x33;
 
7226                         dtraceProbeSite[1] = 0xC0;              
 
7227                         dtraceProbeSite[2] = 0x90;              // 1-byte nop
 
7228                         dtraceProbeSite[3] = 0x90;              // 1-byte nop
 
7230                 case x86_64::kDtraceTypeReference:
 
7231                 case x86_64::kDtraceProbe:
 
7232                         // nothing to fix up
 
7238 void Writer<x86_64>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
7240         const int64_t twoGigLimit                 = 0x7FFFFFFF;
 
7241         bool external = this->makesExternalRelocatableReference(ref->getTarget());
 
7242         uint64_t* fixUp = (uint64_t*)&buffer[ref->getFixUpOffset()];
 
7243         int64_t displacement = 0;
 
7245         switch ( (x86_64::ReferenceKinds)(ref->getKind()) ) {
 
7246                 case x86_64::kNoFixUp:
 
7247                 case x86_64::kGOTNoFixUp:
 
7248                 case x86_64::kFollowOn:
 
7249                 case x86_64::kGroupSubordinate:
 
7252                 case x86_64::kPointer:
 
7253                 case x86_64::kPointerWeakImport:
 
7256                                         // external relocation ==> pointer contains addend
 
7257                                         LittleEndian::set64(*fixUp, ref->getTargetOffset());
 
7260                                         // internal relocation ==> pointer contains target address
 
7261                                         LittleEndian::set64(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
7265                 case x86_64::kPointer32:
 
7268                                         // external relocation ==> pointer contains addend
 
7269                                         LittleEndian::set32(*((uint32_t*)fixUp), ref->getTargetOffset());
 
7272                                         // internal relocation ==> pointer contains target address
 
7273                                         LittleEndian::set32(*((uint32_t*)fixUp), ref->getTarget().getAddress() + ref->getTargetOffset());
 
7277                 case x86_64::kPointerDiff32:
 
7278                                 displacement = ref->getTargetOffset() - ref->getFromTargetOffset();
 
7279                                 if ( ref->getTarget().getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn )
 
7280                                         displacement += ref->getTarget().getAddress();
 
7281                                 if ( ref->getFromTarget().getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn ) 
 
7282                                         displacement -= ref->getFromTarget().getAddress();
 
7283                                 LittleEndian::set32(*((uint32_t*)fixUp), displacement);
 
7285                 case x86_64::kPointerDiff:
 
7286                                 displacement = ref->getTargetOffset() - ref->getFromTargetOffset();
 
7287                                 if ( ref->getTarget().getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn )
 
7288                                         displacement += ref->getTarget().getAddress();
 
7289                                 if ( ref->getFromTarget().getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableNotIn ) 
 
7290                                         displacement -= ref->getFromTarget().getAddress();
 
7291                                 LittleEndian::set64(*fixUp, displacement);
 
7293                 case x86_64::kBranchPCRel32:
 
7294                 case x86_64::kBranchPCRel32WeakImport:
 
7295                 case x86_64::kDtraceProbeSite:
 
7296                 case x86_64::kDtraceIsEnabledSite:
 
7297                 case x86_64::kPCRel32:
 
7298                 case x86_64::kPCRel32_1:
 
7299                 case x86_64::kPCRel32_2:
 
7300                 case x86_64::kPCRel32_4:
 
7301                         // turn unsigned 64-bit target offset in signed 32-bit offset, since that is what source originally had
 
7302                         temp32 = ref->getTargetOffset();
 
7304                                 // extern relocation contains addend
 
7305                                 displacement = temp32;
 
7308                                 // internal relocations contain delta to target address
 
7309                                 displacement = (ref->getTarget().getAddress() + temp32) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
7311                         switch ( ref->getKind() ) {
 
7312                                 case x86_64::kPCRel32_1:
 
7315                                 case x86_64::kPCRel32_2:
 
7318                                 case x86_64::kPCRel32_4:
 
7322                         if ( (displacement > twoGigLimit) || (displacement < (-twoGigLimit)) ) {
 
7323                                 //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
 
7324                                 throw "rel32 out of range";
 
7326                         LittleEndian::set32(*((uint32_t*)fixUp), (int32_t)displacement);
 
7328                 case x86_64::kBranchPCRel8:
 
7329                         // turn unsigned 64-bit target offset in signed 32-bit offset, since that is what source originally had
 
7330                         temp32 = ref->getTargetOffset();
 
7332                                 // extern relocation contains addend
 
7333                                 displacement = temp32;
 
7336                                 // internal relocations contain delta to target address
 
7337                                 displacement = (ref->getTarget().getAddress() + temp32) - (inAtom->getAddress() + ref->getFixUpOffset() + 1);
 
7339                         if ( (displacement > 127) || (displacement < (-128)) ) {
 
7340                                 //fprintf(stderr, "call out of range from %s in %s to %s in %s\n", this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
 
7341                                 throw "rel8 out of range";
 
7343                         *((int8_t*)fixUp) = (int8_t)displacement;
 
7345                 case x86_64::kPCRel32GOT:
 
7346                 case x86_64::kPCRel32GOTLoad:
 
7347                 case x86_64::kPCRel32GOTWeakImport:
 
7348                 case x86_64::kPCRel32GOTLoadWeakImport:
 
7349                         // contains addend (usually zero)
 
7350                         LittleEndian::set32(*((uint32_t*)fixUp), (uint32_t)(ref->getTargetOffset()));
 
7352                 case x86_64::kPointerDiff24:
 
7353                         throw "internal linker error, kPointerDiff24 can't be encoded into object files";
 
7354                 case x86_64::kImageOffset32:
 
7355                         throw "internal linker error, kImageOffset32 can't be encoded into object files";
 
7356                 case x86_64::kSectionOffset24:
 
7357                         throw "internal linker error, kSectionOffset24 can't be encoded into object files";
 
7358                 case x86_64::kDtraceTypeReference:
 
7359                 case x86_64::kDtraceProbe:
 
7360                         // nothing to fix up
 
7366 void Writer<ppc>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
7368         fixUpReference_powerpc(ref, inAtom, buffer, true);
 
7372 void Writer<ppc64>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
7374         fixUpReference_powerpc(ref, inAtom, buffer, true);
 
7378 void Writer<ppc>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
7380         fixUpReference_powerpc(ref, inAtom, buffer, false);
 
7384 void Writer<ppc64>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
7386         fixUpReference_powerpc(ref, inAtom, buffer, false);
 
7390 // ppc and ppc64 are mostly the same, so they share a template specialzation
 
7392 template <typename A>
 
7393 void Writer<A>::fixUpReference_powerpc(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[], bool finalLinkedImage) const
 
7395         uint32_t        instruction;
 
7396         uint32_t        newInstruction;
 
7397         int64_t         displacement;
 
7398         uint64_t        targetAddr = 0;
 
7399         uint64_t        picBaseAddr;
 
7400         uint16_t        instructionLowHalf;
 
7401         uint16_t        instructionHighHalf;
 
7402         uint32_t*       fixUp = (uint32_t*)&buffer[ref->getFixUpOffset()];
 
7403         pint_t*         fixUpPointer = (pint_t*)&buffer[ref->getFixUpOffset()];
 
7404         bool            relocateableExternal = false;
 
7405         const int64_t picbase_twoGigLimit = 0x80000000;
 
7407         if ( ref->getTargetBinding() != ObjectFile::Reference::kDontBind ) {
 
7408                 targetAddr = ref->getTarget().getAddress() + ref->getTargetOffset();
 
7409                 if ( finalLinkedImage )
 
7410                         relocateableExternal = (relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal);
 
7412                         relocateableExternal = this->makesExternalRelocatableReference(ref->getTarget());       
 
7415         switch ( (typename A::ReferenceKinds)(ref->getKind()) ) {
 
7418                 case A::kGroupSubordinate:
 
7421                 case A::kPointerWeakImport:
 
7424                                 //fprintf(stderr, "fixUpReferenceFinal: %s reference to %s\n", this->getDisplayName(), target.getDisplayName());
 
7425                                 if ( finalLinkedImage && (((SectionInfo*)inAtom->getSection())->fAllLazyPointers 
 
7426                                                                            || ((SectionInfo*)inAtom->getSection())->fAllLazyDylibPointers) ) {
 
7427                                         switch (ref->getTarget().getDefinitionKind()) {
 
7428                                                 case ObjectFile::Atom::kExternalDefinition:
 
7429                                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
7430                                                         // prebound lazy pointer to another dylib ==> pointer contains zero
 
7431                                                         P::setP(*fixUpPointer, 0);
 
7433                                                 case ObjectFile::Atom::kTentativeDefinition:
 
7434                                                 case ObjectFile::Atom::kRegularDefinition:
 
7435                                                 case ObjectFile::Atom::kWeakDefinition:
 
7436                                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
7437                                                         // prebound lazy pointer to withing this dylib ==> pointer contains address
 
7438                                                         P::setP(*fixUpPointer, targetAddr);
 
7442                                 else if ( !finalLinkedImage && ((SectionInfo*)inAtom->getSection())->fAllNonLazyPointers ) {
 
7443                                         // if INDIRECT_SYMBOL_LOCAL the content is pointer, else it is zero
 
7444                                         if ( this->indirectSymbolInRelocatableIsLocal(ref) ) 
 
7445                                                 P::setP(*fixUpPointer, targetAddr);
 
7447                                                 P::setP(*fixUpPointer, 0);
 
7449                                 else if ( relocateableExternal ) {
 
7450                                         if ( fOptions.prebind() ) {
 
7451                                                 switch (ref->getTarget().getDefinitionKind()) {
 
7452                                                         case ObjectFile::Atom::kExternalDefinition:
 
7453                                                         case ObjectFile::Atom::kExternalWeakDefinition:
 
7454                                                                 // prebound external relocation ==> pointer contains addend
 
7455                                                                 P::setP(*fixUpPointer, ref->getTargetOffset());
 
7457                                                         case ObjectFile::Atom::kTentativeDefinition:
 
7458                                                         case ObjectFile::Atom::kRegularDefinition:
 
7459                                                         case ObjectFile::Atom::kWeakDefinition:
 
7460                                                                 // prebound external relocation to internal atom ==> pointer contains target address + addend
 
7461                                                                 P::setP(*fixUpPointer, targetAddr);
 
7463                                                         case ObjectFile::Atom::kAbsoluteSymbol:
 
7468                                                 // external relocation ==> pointer contains addend
 
7469                                                 P::setP(*fixUpPointer, ref->getTargetOffset());
 
7473                                         // internal relocation
 
7474                                         if ( finalLinkedImage || (ref->getTarget().getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition)  ) {
 
7475                                                 // pointer contains target address
 
7476                                                 //printf("Atom::fixUpReference_powerpc() target.name=%s, target.address=0x%08llX\n",  ref->getTarget().getDisplayName(), targetAddr);
 
7477                                                 P::setP(*fixUpPointer, targetAddr);
 
7480                                                 // pointer contains addend
 
7481                                                 P::setP(*fixUpPointer, ref->getTargetOffset());
 
7486                 case A::kPointerDiff64:
 
7487                         P::setP(*fixUpPointer, targetAddr - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
 
7489                 case A::kPointerDiff32:
 
7490                         P::E::set32(*fixUp, targetAddr - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
 
7492                 case A::kPointerDiff16:
 
7493                         P::E::set16(*((uint16_t*)fixUp), targetAddr - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
 
7495                 case A::kDtraceProbeSite:
 
7496                         if ( finalLinkedImage ) {
 
7497                                 // change call site to a NOP
 
7498                                 BigEndian::set32(*fixUp, 0x60000000);
 
7501                                 // set  bl instuction to branch to address zero in .o file
 
7502                                 int64_t displacement = ref->getTargetOffset() - (inAtom->getAddress() + ref->getFixUpOffset());
 
7503                                 instruction = BigEndian::get32(*fixUp);
 
7504                                 newInstruction = (instruction & 0xFC000003) | ((uint32_t)displacement & 0x03FFFFFC);
 
7505                                 BigEndian::set32(*fixUp, newInstruction);
 
7508                 case A::kDtraceIsEnabledSite:
 
7509                         if ( finalLinkedImage ) {
 
7510                                 // change call site to a li r3,0
 
7511                                 BigEndian::set32(*fixUp, 0x38600000);
 
7514                                 // set  bl instuction to branch to address zero in .o file
 
7515                                 int64_t displacement = ref->getTargetOffset() - (inAtom->getAddress() + ref->getFixUpOffset());
 
7516                                 instruction = BigEndian::get32(*fixUp);
 
7517                                 newInstruction = (instruction & 0xFC000003) | ((uint32_t)displacement & 0x03FFFFFC);
 
7518                                 BigEndian::set32(*fixUp, newInstruction);
 
7521                 case A::kBranch24WeakImport:
 
7524                                 //fprintf(stderr, "bl fixup to %s at 0x%08llX, ", target.getDisplayName(), target.getAddress());
 
7525                                 int64_t displacement = targetAddr - (inAtom->getAddress() + ref->getFixUpOffset());
 
7526                                 if ( relocateableExternal )  {
 
7527                                         // doing "ld -r" to an external symbol
 
7528                                         // the mach-o way of encoding this is that the bl instruction's target addr is the offset into the target
 
7529                                         displacement -= ref->getTarget().getAddress();
 
7532                                         const int64_t bl_eightMegLimit = 0x00FFFFFF;
 
7533                                         if ( (displacement > bl_eightMegLimit) || (displacement < (-bl_eightMegLimit)) ) {
 
7534                                                 //fprintf(stderr, "bl out of range (%lld max is +/-16M) from %s in %s to %s in %s\n", displacement, this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
 
7535                                                 throwf("bl out of range (%lld max is +/-16M) from %s at 0x%08llX in %s of %s to %s at 0x%08llX in %s of  %s",
 
7536                                                         displacement, inAtom->getDisplayName(), inAtom->getAddress(), inAtom->getSectionName(), inAtom->getFile()->getPath(),
 
7537                                                         ref->getTarget().getDisplayName(), ref->getTarget().getAddress(), ref->getTarget().getSectionName(), ref->getTarget().getFile()->getPath());
 
7540                                 instruction = BigEndian::get32(*fixUp);
 
7541                                 newInstruction = (instruction & 0xFC000003) | ((uint32_t)displacement & 0x03FFFFFC);
 
7542                                 //fprintf(stderr, "bl fixup: 0x%08X -> 0x%08X\n", instruction, newInstruction);
 
7543                                 BigEndian::set32(*fixUp, newInstruction);
 
7548                                 int64_t displacement = targetAddr - (inAtom->getAddress() + ref->getFixUpOffset());
 
7549                                 if ( relocateableExternal )  {
 
7550                                         // doing "ld -r" to an external symbol
 
7551                                         // the mach-o way of encoding this is that the bl instruction's target addr is the offset into the target
 
7552                                         displacement -= ref->getTarget().getAddress();
 
7554                                 const int64_t b_sixtyFourKiloLimit = 0x0000FFFF;
 
7555                                 if ( (displacement > b_sixtyFourKiloLimit) || (displacement < (-b_sixtyFourKiloLimit)) ) {
 
7556                                         //fprintf(stderr, "bl out of range (%lld max is +/-16M) from %s in %s to %s in %s\n", displacement, this->getDisplayName(), this->getFile()->getPath(), target.getDisplayName(), target.getFile()->getPath());
 
7557                                         throwf("bcc out of range (%lld max is +/-64K) from %s in %s to %s in %s",
 
7558                                                 displacement, inAtom->getDisplayName(), inAtom->getFile()->getPath(),
 
7559                                                 ref->getTarget().getDisplayName(), ref->getTarget().getFile()->getPath());
 
7562                                 //fprintf(stderr, "bcc fixup displacement=0x%08llX, atom.addr=0x%08llX, atom.offset=0x%08X\n", displacement, inAtom->getAddress(), (uint32_t)ref->getFixUpOffset());
 
7563                                 instruction = BigEndian::get32(*fixUp);
 
7564                                 newInstruction = (instruction & 0xFFFF0003) | ((uint32_t)displacement & 0x0000FFFC);
 
7565                                 //fprintf(stderr, "bc fixup: 0x%08X -> 0x%08X\n", instruction, newInstruction);
 
7566                                 BigEndian::set32(*fixUp, newInstruction);
 
7569                 case A::kPICBaseLow16:
 
7570                         picBaseAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
 
7571                         displacement = targetAddr - picBaseAddr;
 
7572                         if ( (displacement > picbase_twoGigLimit) || (displacement < (-picbase_twoGigLimit)) )
 
7573                                 throw "32-bit pic-base out of range";
 
7574                         instructionLowHalf = (displacement & 0xFFFF);
 
7575                         instruction = BigEndian::get32(*fixUp);
 
7576                         newInstruction = (instruction & 0xFFFF0000) | instructionLowHalf;
 
7577                         BigEndian::set32(*fixUp, newInstruction);
 
7579                 case A::kPICBaseLow14:
 
7580                         picBaseAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
 
7581                         displacement = targetAddr - picBaseAddr;
 
7582                         if ( (displacement > picbase_twoGigLimit) || (displacement < (-picbase_twoGigLimit)) )
 
7583                                 throw "32-bit pic-base out of range";
 
7584                         if ( (displacement & 0x3) != 0 )
 
7585                                 throwf("bad offset (0x%08X) for lo14 instruction pic-base fix-up", (uint32_t)displacement);
 
7586                         instructionLowHalf = (displacement & 0xFFFC);
 
7587                         instruction = BigEndian::get32(*fixUp);
 
7588                         newInstruction = (instruction & 0xFFFF0003) | instructionLowHalf;
 
7589                         BigEndian::set32(*fixUp, newInstruction);
 
7591                 case A::kPICBaseHigh16:
 
7592                         picBaseAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
 
7593                         displacement = targetAddr - picBaseAddr;
 
7594                         if ( (displacement > picbase_twoGigLimit) || (displacement < (-picbase_twoGigLimit)) )
 
7595                                 throw "32-bit pic-base out of range";
 
7596                         instructionLowHalf = displacement >> 16;
 
7597                         if ( (displacement & 0x00008000) != 0 )
 
7598                                 ++instructionLowHalf;
 
7599                         instruction = BigEndian::get32(*fixUp);
 
7600                         newInstruction = (instruction & 0xFFFF0000) | instructionLowHalf;
 
7601                         BigEndian::set32(*fixUp, newInstruction);
 
7604                         if ( relocateableExternal && !finalLinkedImage )
 
7605                                 targetAddr -= ref->getTarget().getAddress();
 
7606                         instructionLowHalf = (targetAddr & 0xFFFF);
 
7607                         instruction = BigEndian::get32(*fixUp);
 
7608                         newInstruction = (instruction & 0xFFFF0000) | instructionLowHalf;
 
7609                         BigEndian::set32(*fixUp, newInstruction);
 
7612                         if ( relocateableExternal && !finalLinkedImage )
 
7613                                 targetAddr -= ref->getTarget().getAddress();
 
7614                         if ( (targetAddr & 0x3) != 0 )
 
7615                                 throw "bad address for absolute lo14 instruction fix-up";
 
7616                         instructionLowHalf = (targetAddr & 0xFFFF);
 
7617                         instruction = BigEndian::get32(*fixUp);
 
7618                         newInstruction = (instruction & 0xFFFF0003) | instructionLowHalf;
 
7619                         BigEndian::set32(*fixUp, newInstruction);
 
7622                         if ( relocateableExternal ) {
 
7623                                 if ( finalLinkedImage ) {
 
7624                                         switch (ref->getTarget().getDefinitionKind()) {
 
7625                                                 case ObjectFile::Atom::kExternalDefinition:
 
7626                                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
7627                                                         throwf("absolute address to symbol %s in a different linkage unit not supported", ref->getTargetName());
 
7629                                                 case ObjectFile::Atom::kTentativeDefinition:
 
7630                                                 case ObjectFile::Atom::kRegularDefinition:
 
7631                                                 case ObjectFile::Atom::kWeakDefinition:
 
7632                                                         // use target address
 
7634                                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
7635                                                         targetAddr = ref->getTarget().getSectionOffset();
 
7640                                         targetAddr -= ref->getTarget().getAddress();
 
7643                         instructionHighHalf = (targetAddr >> 16);
 
7644                         instruction = BigEndian::get32(*fixUp);
 
7645                         newInstruction = (instruction & 0xFFFF0000) | instructionHighHalf;
 
7646                         BigEndian::set32(*fixUp, newInstruction);
 
7648                 case A::kAbsHigh16AddLow:
 
7649                         if ( relocateableExternal ) {
 
7650                                 if ( finalLinkedImage ) {
 
7651                                         switch (ref->getTarget().getDefinitionKind()) {
 
7652                                                 case ObjectFile::Atom::kExternalDefinition:
 
7653                                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
7654                                                         throwf("absolute address to symbol %s in a different linkage unit not supported", ref->getTargetName());
 
7656                                                 case ObjectFile::Atom::kTentativeDefinition:
 
7657                                                 case ObjectFile::Atom::kRegularDefinition:
 
7658                                                 case ObjectFile::Atom::kWeakDefinition:
 
7659                                                         // use target address
 
7661                                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
7662                                                         targetAddr = ref->getTarget().getSectionOffset();
 
7667                                         targetAddr -= ref->getTarget().getAddress();
 
7670                         if ( targetAddr & 0x00008000 )
 
7671                                 targetAddr += 0x00010000;
 
7672                         instruction = BigEndian::get32(*fixUp);
 
7673                         newInstruction = (instruction & 0xFFFF0000) | (targetAddr >> 16);
 
7674                         BigEndian::set32(*fixUp, newInstruction);
 
7676                 case A::kDtraceTypeReference:
 
7677                 case A::kDtraceProbe:
 
7678                         // nothing to fix up
 
7684 bool Writer<ppc>::stubableReference(const ObjectFile::Atom* inAtom, const ObjectFile::Reference* ref)
 
7686         uint8_t kind = ref->getKind();
 
7687         switch ( (ppc::ReferenceKinds)kind ) {
 
7689                 case ppc::kFollowOn:
 
7690                 case ppc::kGroupSubordinate:
 
7692                 case ppc::kPointerWeakImport:
 
7693                 case ppc::kPointerDiff16:
 
7694                 case ppc::kPointerDiff32:
 
7695                 case ppc::kPointerDiff64:
 
7696                 case ppc::kDtraceProbe:
 
7697                 case ppc::kDtraceProbeSite:
 
7698                 case ppc::kDtraceIsEnabledSite:
 
7699                 case ppc::kDtraceTypeReference:
 
7700                         // these are never used to call external functions
 
7702                 case ppc::kBranch24: 
 
7703                 case ppc::kBranch24WeakImport: 
 
7704                 case ppc::kBranch14: 
 
7705                         // these are used to call external functions
 
7707                 case ppc::kPICBaseLow16:
 
7708                 case ppc::kPICBaseLow14:
 
7709                 case ppc::kPICBaseHigh16:
 
7710                 case ppc::kAbsLow16:
 
7711                 case ppc::kAbsLow14:
 
7712                 case ppc::kAbsHigh16:
 
7713                 case ppc::kAbsHigh16AddLow:
 
7714                         // these are only used to call external functions
 
7715                         // in -mlong-branch stubs
 
7716                         switch ( ref->getTarget().getDefinitionKind() ) {
 
7717                                 case ObjectFile::Atom::kExternalDefinition:
 
7718                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
7719                                         // if the .o file this atom came from has long-branch stubs,
 
7720                                         // then assume these instructions in a stub.
 
7721                                         // Otherwise, these are a direct reference to something (maybe a runtime text reloc)
 
7722                                         return ( inAtom->getFile()->hasLongBranchStubs() );
 
7723                                 case ObjectFile::Atom::kTentativeDefinition:
 
7724                                 case ObjectFile::Atom::kRegularDefinition:
 
7725                                 case ObjectFile::Atom::kWeakDefinition:
 
7726                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
7735 bool Writer<arm>::stubableReference(const ObjectFile::Atom* inAtom, const ObjectFile::Reference* ref)
 
7737         uint8_t kind = ref->getKind();
 
7738         switch ( (arm::ReferenceKinds)kind ) {
 
7739                 case arm::kBranch24:
 
7740                 case arm::kBranch24WeakImport:
 
7742                 case arm::kThumbBranch22:
 
7743                 case arm::kThumbBranch22WeakImport:
 
7744                         fHasThumbBranches = true;
 
7747                 case arm::kFollowOn:
 
7748                 case arm::kGroupSubordinate:
 
7750                 case arm::kReadOnlyPointer:
 
7751                 case arm::kPointerWeakImport:
 
7752                 case arm::kPointerDiff:
 
7753                 case arm::kDtraceProbe:
 
7754                 case arm::kDtraceProbeSite:
 
7755                 case arm::kDtraceIsEnabledSite:
 
7756                 case arm::kDtraceTypeReference:
 
7757                 case arm::kPointerDiff12:
 
7764 bool Writer<ppc64>::stubableReference(const ObjectFile::Atom* inAtom, const ObjectFile::Reference* ref)
 
7766         uint8_t kind = ref->getKind();
 
7767         switch ( (ppc64::ReferenceKinds)kind ) {
 
7769                 case ppc::kFollowOn:
 
7770                 case ppc::kGroupSubordinate:
 
7772                 case ppc::kPointerWeakImport:
 
7773                 case ppc::kPointerDiff16:
 
7774                 case ppc::kPointerDiff32:
 
7775                 case ppc::kPointerDiff64:
 
7776                 case ppc::kPICBaseLow16:
 
7777                 case ppc::kPICBaseLow14:
 
7778                 case ppc::kPICBaseHigh16:
 
7779                 case ppc::kAbsLow16:
 
7780                 case ppc::kAbsLow14:
 
7781                 case ppc::kAbsHigh16:
 
7782                 case ppc::kAbsHigh16AddLow:
 
7783                 case ppc::kDtraceProbe:
 
7784                 case ppc::kDtraceProbeSite:
 
7785                 case ppc::kDtraceIsEnabledSite:
 
7786                 case ppc::kDtraceTypeReference:
 
7787                         // these are never used to call external functions
 
7789                 case ppc::kBranch24: 
 
7790                 case ppc::kBranch24WeakImport: 
 
7791                 case ppc::kBranch14: 
 
7792                         // these are used to call external functions
 
7799 bool Writer<x86>::stubableReference(const ObjectFile::Atom* inAtom, const ObjectFile::Reference* ref)
 
7801         uint8_t kind = ref->getKind();
 
7802         return (kind == x86::kPCRel32 || kind == x86::kPCRel32WeakImport);
 
7806 bool Writer<x86_64>::stubableReference(const ObjectFile::Atom* inAtom, const ObjectFile::Reference* ref)
 
7808         uint8_t kind = ref->getKind();
 
7809         return (kind == x86_64::kBranchPCRel32 || kind == x86_64::kBranchPCRel32WeakImport);
 
7814 bool Writer<ppc>::weakImportReferenceKind(uint8_t kind)
 
7816         return (kind == ppc::kBranch24WeakImport || kind == ppc::kPointerWeakImport);
 
7820 bool Writer<ppc64>::weakImportReferenceKind(uint8_t kind)
 
7822         return (kind == ppc64::kBranch24WeakImport || kind == ppc64::kPointerWeakImport);
 
7826 bool Writer<x86>::weakImportReferenceKind(uint8_t kind)
 
7828         return (kind == x86::kPCRel32WeakImport || kind == x86::kPointerWeakImport);
 
7832 bool Writer<x86_64>::weakImportReferenceKind(uint8_t kind)
 
7835                 case x86_64::kPointerWeakImport:
 
7836                 case x86_64::kBranchPCRel32WeakImport:
 
7837                 case x86_64::kPCRel32GOTWeakImport:
 
7838                 case x86_64::kPCRel32GOTLoadWeakImport:
 
7845 bool Writer<arm>::weakImportReferenceKind(uint8_t kind)
 
7847         return (kind == arm::kBranch24WeakImport || kind == arm::kThumbBranch22WeakImport ||
 
7848             kind == arm::kPointerWeakImport);
 
7852 bool Writer<ppc>::GOTReferenceKind(uint8_t kind)
 
7858 bool Writer<ppc64>::GOTReferenceKind(uint8_t kind)
 
7864 bool Writer<x86>::GOTReferenceKind(uint8_t kind)
 
7870 bool Writer<x86_64>::GOTReferenceKind(uint8_t kind)
 
7873                 case x86_64::kPCRel32GOT:
 
7874                 case x86_64::kPCRel32GOTWeakImport:
 
7875                 case x86_64::kPCRel32GOTLoad:
 
7876                 case x86_64::kPCRel32GOTLoadWeakImport:
 
7877                 case x86_64::kGOTNoFixUp:
 
7884 bool Writer<arm>::GOTReferenceKind(uint8_t kind)
 
7890 bool Writer<ppc>::optimizableGOTReferenceKind(uint8_t kind)
 
7896 bool Writer<ppc64>::optimizableGOTReferenceKind(uint8_t kind)
 
7902 bool Writer<x86>::optimizableGOTReferenceKind(uint8_t kind)
 
7908 bool Writer<x86_64>::optimizableGOTReferenceKind(uint8_t kind)
 
7911                 case x86_64::kPCRel32GOTLoad:
 
7912                 case x86_64::kPCRel32GOTLoadWeakImport:
 
7919 bool Writer<arm>::optimizableGOTReferenceKind(uint8_t kind)
 
7924 // 64-bit architectures never need module table, 32-bit sometimes do for backwards compatiblity
 
7925 template <typename A> bool Writer<A>::needsModuleTable() {return fOptions.needsModuleTable(); }
 
7926 template <> bool Writer<ppc64>::needsModuleTable() { return false; }
 
7927 template <> bool Writer<x86_64>::needsModuleTable() { return false; }
 
7930 template <typename A>
 
7931 void Writer<A>::optimizeDylibReferences()
 
7933         //fprintf(stderr, "original ordinals table:\n");
 
7934         //for (std::map<class ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {
 
7935         //      fprintf(stderr, "%u <== %p/%s\n", it->second, it->first, it->first->getPath());
 
7937         // find unused dylibs that can be removed
 
7938         std::map<uint32_t, ObjectFile::Reader*> ordinalToReader;
 
7939         std::map<ObjectFile::Reader*, ObjectFile::Reader*> readerAliases;
 
7940         for (std::map<ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {   
 
7941                 ObjectFile::Reader* reader = it->first;
 
7942                 std::map<ObjectFile::Reader*, ObjectFile::Reader*>::iterator aliasPos = fLibraryAliases.find(reader);
 
7943                 if ( aliasPos != fLibraryAliases.end() ) {
 
7944                         // already noticed that this reader has same install name as another reader
 
7945                         readerAliases[reader] = aliasPos->second;
 
7947                 else if ( !reader->providedExportAtom() && (reader->implicitlyLinked() || reader->deadStrippable() || fOptions.deadStripDylibs()) ) {
 
7948                         // this reader can be optimized away
 
7949                         it->second = 0xFFFFFFFF;
 
7950                         typename std::map<class ObjectFile::Reader*, class DylibLoadCommandsAtom<A>* >::iterator pos = fLibraryToLoadCommand.find(reader);
 
7951                         if ( pos != fLibraryToLoadCommand.end() ) 
 
7952                                 pos->second->optimizeAway();
 
7955                         // mark this reader as using it ordinal
 
7956                         std::map<uint32_t, ObjectFile::Reader*>::iterator pos = ordinalToReader.find(it->second);
 
7957                         if ( pos == ordinalToReader.end() ) 
 
7958                                 ordinalToReader[it->second] = reader;
 
7960                                 readerAliases[reader] = pos->second;
 
7963         // renumber ordinals (depends on iterator walking in ordinal order)
 
7964         // all LC_LAZY_LOAD_DYLIB load commands must have highest ordinals
 
7965         uint32_t newOrdinal = 0;
 
7966         for (std::map<uint32_t, ObjectFile::Reader*>::iterator it = ordinalToReader.begin(); it != ordinalToReader.end(); ++it) {
 
7967                 if ( it->first <= fLibraryToOrdinal.size() ) {
 
7968                         if ( ! it->second->isLazyLoadedDylib() )
 
7969                                 fLibraryToOrdinal[it->second] = ++newOrdinal;
 
7972         for (std::map<uint32_t, ObjectFile::Reader*>::iterator it = ordinalToReader.begin(); it != ordinalToReader.end(); ++it) {
 
7973                 if ( it->first <= fLibraryToOrdinal.size() ) {
 
7974                         if ( it->second->isLazyLoadedDylib() ) {
 
7975                                 fLibraryToOrdinal[it->second] = ++newOrdinal;
 
7980         // <rdar://problem/5504954> linker does not error when dylib ordinal exceeds 250
 
7981         if ( (newOrdinal >= MAX_LIBRARY_ORDINAL) && (fOptions.nameSpace() == Options::kTwoLevelNameSpace) )
 
7982                 throwf("two level namespace mach-o files can link with at most %d dylibs, this link would use %d dylibs", MAX_LIBRARY_ORDINAL, newOrdinal);
 
7984         // add aliases (e.g. -lm points to libSystem.dylib)
 
7985         for (std::map<ObjectFile::Reader*, ObjectFile::Reader*>::iterator it = readerAliases.begin(); it != readerAliases.end(); ++it) {
 
7986                 fLibraryToOrdinal[it->first] = fLibraryToOrdinal[it->second];
 
7989         //fprintf(stderr, "new ordinals table:\n");
 
7990         //for (std::map<class ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {
 
7991         //      fprintf(stderr, "%u <== %p/%s\n", it->second, it->first, it->first->getPath());
 
7997 void Writer<arm>::scanForAbsoluteReferences()
 
7999         // arm codegen never has absolute references.  FIXME: Is this correct?
 
8003 void Writer<x86_64>::scanForAbsoluteReferences()
 
8005         // x86_64 codegen never has absolute references
 
8009 void  Writer<x86>::scanForAbsoluteReferences()
 
8011         // when linking -pie verify there are no absolute addressing, unless -read_only_relocs is also used
 
8012         if ( fOptions.positionIndependentExecutable() && !fOptions.allowTextRelocs() ) {
 
8013                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
8014                         ObjectFile::Atom* atom = *it;
 
8015                         if ( atom->getContentType() == ObjectFile::Atom::kStub )
 
8017                         if ( atom->getContentType() == ObjectFile::Atom::kStubHelper )
 
8019                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
8020                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
8021                                 ObjectFile::Reference* ref = *rit;
 
8022                                 switch (ref->getKind()) {
 
8023                                         case x86::kAbsolute32:
 
8024                                                 throwf("cannot link -pie: -mdynamic-no-pic codegen found in %s from %s", atom->getDisplayName(), atom->getFile()->getPath());
 
8033 void  Writer<ppc>::scanForAbsoluteReferences()
 
8035         // when linking -pie verify there are no absolute addressing, unless -read_only_relocs is also used
 
8036         if ( fOptions.positionIndependentExecutable()  && !fOptions.allowTextRelocs() ) {
 
8037                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
8038                         ObjectFile::Atom* atom = *it;
 
8039                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
8040                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
8041                                 ObjectFile::Reference* ref = *rit;
 
8042                                 switch (ref->getKind()) {
 
8043                                         case ppc::kAbsLow16:
 
8044                                         case ppc::kAbsLow14:
 
8045                                         case ppc::kAbsHigh16:
 
8046                                         case ppc::kAbsHigh16AddLow:
 
8047                                                 throwf("cannot link -pie: -mdynamic-no-pic codegen found in %s from %s", atom->getDisplayName(), atom->getFile()->getPath());
 
8056 // for ppc64 look for any -mdynamic-no-pic codegen
 
8058 void  Writer<ppc64>::scanForAbsoluteReferences()
 
8060         // only do this for main executable
 
8061         if ( mightNeedPadSegment() && (fPageZeroAtom != NULL) ) {
 
8062                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
8063                         ObjectFile::Atom* atom = *it;
 
8064                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
8065                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
8066                                 ObjectFile::Reference* ref = *rit;
 
8067                                 switch (ref->getKind()) {
 
8068                                         case ppc64::kAbsLow16:
 
8069                                         case ppc64::kAbsLow14:
 
8070                                         case ppc64::kAbsHigh16:
 
8071                                         case ppc64::kAbsHigh16AddLow:
 
8072                                                 //fprintf(stderr, "found -mdynamic-no-pic codegen in %s in %s\n", atom->getDisplayName(), atom->getFile()->getPath());
 
8073                                                 // shrink page-zero and add pad segment to compensate
 
8074                                                 fPadSegmentInfo = new SegmentInfo(4096);
 
8075                                                 strcpy(fPadSegmentInfo->fName, "__4GBFILL");
 
8076                                                 fPageZeroAtom->setSize(0x1000);
 
8085 template <typename A>
 
8086 void Writer<A>::insertDummyStubs()
 
8088         // only needed for x86
 
8092 void Writer<x86>::insertDummyStubs()
 
8094         // any 5-byte stubs that cross a 32-byte cache line may update incorrectly
 
8095         std::vector<class StubAtom<x86>*>        betterStubs;
 
8096         for (std::vector<class StubAtom<x86>*>::iterator it=fAllSynthesizedStubs.begin(); it != fAllSynthesizedStubs.end(); it++) {
 
8097                 switch (betterStubs.size() % 64 ) {
 
8098                         case 12:// stub would occupy 0x3C->0x41
 
8099                         case 25:// stub would occupy 0x7D->0x82
 
8100                         case 38:// stub would occupy 0xBE->0xC3
 
8101                         case 51:// stub would occupy 0xFF->0x04
 
8102                                 betterStubs.push_back(new StubAtom<x86>(*this, *((ObjectFile::Atom*)NULL), false)); //pad with dummy stub
 
8105                 betterStubs.push_back(*it);
 
8108         fAllSynthesizedStubs.clear();
 
8109         fAllSynthesizedStubs.insert(fAllSynthesizedStubs.begin(), betterStubs.begin(), betterStubs.end());
 
8113 template <typename A>
 
8114 void Writer<A>::synthesizeKextGOT(const std::vector<class ObjectFile::Atom*>& existingAtoms,
 
8115                                                                         std::vector<class ObjectFile::Atom*>& newAtoms)
 
8117         // walk every atom and reference
 
8118         for (std::vector<ObjectFile::Atom*>::const_iterator it=existingAtoms.begin(); it != existingAtoms.end(); it++) {
 
8119                 const ObjectFile::Atom* atom = *it;
 
8120                 std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
8121                 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
8122                         ObjectFile::Reference* ref = *rit;
 
8123                         switch ( ref->getTargetBinding()) {
 
8124                                 case ObjectFile::Reference::kUnboundByName:
 
8125                                 case ObjectFile::Reference::kDontBind:
 
8127                                 case ObjectFile::Reference::kBoundByName:
 
8128                                 case ObjectFile::Reference::kBoundDirectly:
 
8129                                         ObjectFile::Atom& target = ref->getTarget();
 
8130                                         // create GOT slots (non-lazy pointers) as needed
 
8131                                         if ( this->GOTReferenceKind(ref->getKind()) ) {
 
8132                                                 bool useGOT = ( this->relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal );
 
8133                                                 // if this GOT usage cannot be optimized away then make a GOT enry
 
8134                                                 if ( ! this->optimizableGOTReferenceKind(ref->getKind()) )
 
8137                                                         ObjectFile::Atom* nlp = NULL;
 
8138                                                         std::map<ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fGOTMap.find(&target);
 
8139                                                         if ( pos == fGOTMap.end() ) {
 
8140                                                                 nlp = new NonLazyPointerAtom<A>(*this, target);
 
8141                                                                 fGOTMap[&target] = nlp;
 
8142                                                                 newAtoms.push_back(nlp);
 
8147                                                         // alter reference to use non lazy pointer instead
 
8148                                                         ref->setTarget(*nlp, ref->getTargetOffset());
 
8151                                         // build map of which symbols need weak importing
 
8152                                         if ( (target.getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
 
8153                                                 || (target.getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
 
8154                                                 if ( this->weakImportReferenceKind(ref->getKind()) ) {
 
8155                                                         fWeakImportMap[&target] = true;
 
8165 template <typename A>
 
8166 void Writer<A>::synthesizeStubs(const std::vector<class ObjectFile::Atom*>& existingAtoms,
 
8167                                                                         std::vector<class ObjectFile::Atom*>& newAtoms)
 
8169         switch ( fOptions.outputKind() ) {
 
8170                 case Options::kObjectFile:
 
8171                 case Options::kPreload:
 
8172                         // these output kinds never have stubs
 
8174                 case Options::kKextBundle:
 
8175                         // new kext need a synthesized GOT only
 
8176                         synthesizeKextGOT(existingAtoms, newAtoms);
 
8178                 case Options::kStaticExecutable:
 
8179                 case Options::kDyld:
 
8180                 case Options::kDynamicLibrary:
 
8181                 case Options::kDynamicBundle:
 
8182                 case Options::kDynamicExecutable:
 
8183                         // try to synthesize stubs for these
 
8187         // walk every atom and reference
 
8188         for (std::vector<ObjectFile::Atom*>::const_iterator it=existingAtoms.begin(); it != existingAtoms.end(); it++) {
 
8189                 ObjectFile::Atom* atom = *it;
 
8190                 std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
8191                 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
8192                         ObjectFile::Reference* ref = *rit;
 
8193                         switch ( ref->getTargetBinding()) {
 
8194                                 case ObjectFile::Reference::kUnboundByName:
 
8195                                 case ObjectFile::Reference::kDontBind:
 
8197                                 case ObjectFile::Reference::kBoundByName:
 
8198                                 case ObjectFile::Reference::kBoundDirectly:
 
8199                                         ObjectFile::Atom& target = ref->getTarget();
 
8200                                         // build map of which symbols need weak importing
 
8201                                         if ( (target.getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
 
8202                                                 || (target.getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
 
8203                                                 bool weakImport = this->weakImportReferenceKind(ref->getKind());
 
8204                                                 // <rdar://problem/5633081> Obj-C Symbols in Leopard Can't Be Weak Linked
 
8205                                                 // dyld in Mac OS X 10.3 and earlier need N_WEAK_REF bit set on undefines to objc symbols
 
8206                                                 // in dylibs that are weakly linked.  
 
8207                                                 if ( (ref->getKind() == A::kNoFixUp) && (strncmp(target.getName(), ".objc_class_name_", 17) == 0) ) {
 
8208                                                         typename std::map<class ObjectFile::Reader*, class DylibLoadCommandsAtom<A>* >::iterator pos;
 
8209                                                         pos = fLibraryToLoadCommand.find(target.getFile());
 
8210                                                         if ( pos != fLibraryToLoadCommand.end() ) {
 
8211                                                                 if ( pos->second->linkedWeak() )
 
8215                                                 // <rdar://problem/6186838> -weak_library no longer forces uses to be weak_import
 
8216                                                 if ( fForcedWeakImportReaders.count(target.getFile()) != 0 ) {
 
8217                                                         fWeakImportMap[&target] = true;
 
8221                                                 std::map<const ObjectFile::Atom*,bool>::iterator pos = fWeakImportMap.find(&target);
 
8222                                                 if ( pos == fWeakImportMap.end() ) {
 
8223                                                         // target not in fWeakImportMap, so add
 
8224                                                         fWeakImportMap[&target] = weakImport;
 
8227                                                         // target in fWeakImportMap, check for weakness mismatch
 
8228                                                         if ( pos->second != weakImport ) {
 
8230                                                                 switch ( fOptions.weakReferenceMismatchTreatment() ) {
 
8231                                                                         case Options::kWeakReferenceMismatchError:
 
8232                                                                                 throwf("mismatching weak references for symbol: %s", target.getName());
 
8233                                                                         case Options::kWeakReferenceMismatchWeak:
 
8236                                                                         case Options::kWeakReferenceMismatchNonWeak:
 
8237                                                                                 pos->second = false;
 
8242                                                 // update if we use a weak_import or a strong import from this dylib
 
8243                                                 if ( fWeakImportMap[&target] )
 
8244                                                         fDylibReadersWithWeakImports.insert(target.getFile());
 
8246                                                         fDylibReadersWithNonWeakImports.insert(target.getFile());
 
8248                                         // create stubs as needed
 
8249                                         if ( this->stubableReference(atom, ref) 
 
8250                                                 && (ref->getTargetOffset() == 0)
 
8251                                                 && this->relocationNeededInFinalLinkedImage(target) == kRelocExternal ) {
 
8252                                                 ObjectFile::Atom* stub = NULL;
 
8253                                                 std::map<const ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fStubsMap.find(&target);
 
8254                                                 if ( pos == fStubsMap.end() ) {
 
8255                                                         bool forLazyDylib = false;
 
8256                                                         switch ( target.getDefinitionKind() ) {
 
8257                                                                 case ObjectFile::Atom::kRegularDefinition:
 
8258                                                                 case ObjectFile::Atom::kWeakDefinition:
 
8259                                                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
8260                                                                 case ObjectFile::Atom::kTentativeDefinition:
 
8262                                                                 case ObjectFile::Atom::kExternalDefinition:
 
8263                                                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
8264                                                                         if ( target.getFile()->isLazyLoadedDylib() )
 
8265                                                                                 forLazyDylib = true;
 
8268                                                         // just-in-time, create GOT slot to dyld_stub_binder
 
8269                                                         if ( fOptions.makeCompressedDyldInfo() && (fFastStubGOTAtom == NULL) ) {
 
8270                                                                 if ( fDyldCompressedHelperAtom == NULL )
 
8271                                                                         throw "missing symbol dyld_stub_binder";
 
8272                                                                 fFastStubGOTAtom = new NonLazyPointerAtom<A>(*this, *fDyldCompressedHelperAtom);
 
8274                                                         stub = new StubAtom<A>(*this, target, forLazyDylib);
 
8275                                                         fStubsMap[&target] = stub;
 
8280                                                 // alter reference to use stub instead
 
8281                                                 ref->setTarget(*stub, 0);
 
8283                                         else if ( fOptions.usingLazyDylibLinking() && target.getFile()->isLazyLoadedDylib() ) {
 
8284                                                 throwf("illegal reference to %s in lazy loaded dylib from %s in %s", 
 
8285                                                                 target.getDisplayName(), atom->getDisplayName(), 
 
8286                                                                 atom->getFile()->getPath());
 
8288                                         // create GOT slots (non-lazy pointers) as needed
 
8289                                         else if ( this->GOTReferenceKind(ref->getKind()) ) {
 
8291                                                 bool mustUseGOT = ( this->relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal );
 
8293                                                 if ( fBiggerThanTwoGigs ) {
 
8294                                                         // in big images use GOT for all zero fill atoms
 
8295                                                         // this is just a heuristic and may need to be re-examined
 
8296                                                         useGOT = mustUseGOT || ref->getTarget().isZeroFill();
 
8299                                                         // < 2GB image so remove all GOT entries that we can
 
8300                                                         useGOT = mustUseGOT;
 
8302                                                 // if this GOT usage cannot be optimized away then make a GOT enry
 
8303                                                 if ( ! this->optimizableGOTReferenceKind(ref->getKind()) )
 
8306                                                         ObjectFile::Atom* nlp = NULL;
 
8307                                                         std::map<ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fGOTMap.find(&target);
 
8308                                                         if ( pos == fGOTMap.end() ) {
 
8309                                                                 nlp = new NonLazyPointerAtom<A>(*this, target);
 
8310                                                                 fGOTMap[&target] = nlp;
 
8315                                                         // alter reference to use non lazy pointer instead
 
8316                                                         ref->setTarget(*nlp, ref->getTargetOffset());
 
8324         std::sort(fAllSynthesizedStubs.begin(), fAllSynthesizedStubs.end(), AtomByNameSorter());
 
8325         // add dummy self-modifying stubs (x86 only)
 
8326         if ( ! fOptions.makeCompressedDyldInfo() )      
 
8327                 this->insertDummyStubs();
 
8328         // set ordinals so sorting is preserved
 
8329         uint32_t sortOrder = 0;
 
8330         for (typename std::vector<StubAtom<A>*>::iterator it=fAllSynthesizedStubs.begin(); it != fAllSynthesizedStubs.end(); it++) 
 
8331                 (*it)->setSortingOrdinal(sortOrder++);
 
8332         std::sort(fAllSynthesizedStubHelpers.begin(), fAllSynthesizedStubHelpers.end(), AtomByNameSorter());
 
8334         // sort lazy pointers
 
8335         std::sort(fAllSynthesizedLazyPointers.begin(), fAllSynthesizedLazyPointers.end(), AtomByNameSorter());
 
8337         for (typename std::vector<LazyPointerAtom<A>*>::iterator it=fAllSynthesizedLazyPointers.begin(); it != fAllSynthesizedLazyPointers.end(); it++) 
 
8338                 (*it)->setSortingOrdinal(sortOrder++);
 
8339         std::sort(fAllSynthesizedLazyDylibPointers.begin(), fAllSynthesizedLazyDylibPointers.end(), AtomByNameSorter());
 
8341         // sort non-lazy pointers
 
8342         std::sort(fAllSynthesizedNonLazyPointers.begin(), fAllSynthesizedNonLazyPointers.end(), AtomByNameSorter());
 
8344         for (typename std::vector<NonLazyPointerAtom<A>*>::iterator it=fAllSynthesizedNonLazyPointers.begin(); it != fAllSynthesizedNonLazyPointers.end(); it++) 
 
8345                 (*it)->setSortingOrdinal(sortOrder++);
 
8346         std::sort(fAllSynthesizedNonLazyPointers.begin(), fAllSynthesizedNonLazyPointers.end(), AtomByNameSorter());
 
8348         // tell linker about all synthesized atoms
 
8349         newAtoms.insert(newAtoms.end(), fAllSynthesizedStubs.begin(), fAllSynthesizedStubs.end());
 
8350         newAtoms.insert(newAtoms.end(), fAllSynthesizedStubHelpers.begin(), fAllSynthesizedStubHelpers.end());
 
8351         newAtoms.insert(newAtoms.end(), fAllSynthesizedLazyPointers.begin(), fAllSynthesizedLazyPointers.end());
 
8352         newAtoms.insert(newAtoms.end(), fAllSynthesizedLazyDylibPointers.begin(), fAllSynthesizedLazyDylibPointers.end());
 
8353         newAtoms.insert(newAtoms.end(), fAllSynthesizedNonLazyPointers.begin(), fAllSynthesizedNonLazyPointers.end());
 
8357 template <typename A>
 
8358 void Writer<A>::createSplitSegContent()
 
8360         // build LC_SEGMENT_SPLIT_INFO once all atoms exist
 
8361         if ( fSplitCodeToDataContentAtom != NULL ) {
 
8362                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
8363                         ObjectFile::Atom* atom = *it;
 
8364                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
8365                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
8366                                 ObjectFile::Reference* ref = *rit;
 
8367                                 switch ( ref->getTargetBinding()) {
 
8368                                         case ObjectFile::Reference::kUnboundByName:
 
8369                                         case ObjectFile::Reference::kDontBind:
 
8371                                         case ObjectFile::Reference::kBoundByName:
 
8372                                         case ObjectFile::Reference::kBoundDirectly:
 
8373                                                 if ( this->segmentsCanSplitApart(*atom, ref->getTarget()) ) {
 
8374                                                         this->addCrossSegmentRef(atom, ref);
 
8380                 // bad codegen may cause LC_SEGMENT_SPLIT_INFO to be removed
 
8381                 adjustLoadCommandsAndPadding();
 
8387 template <typename A>
 
8388 void Writer<A>::synthesizeUnwindInfoTable()
 
8390         if ( fUnwindInfoAtom != NULL ) {
 
8391                 // walk every atom and gets its unwind info
 
8392                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
8393                         ObjectFile::Atom* atom = *it;
 
8394                         if ( atom->beginUnwind() == atom->endUnwind() ) {
 
8395                                 // be sure to mark that we have no unwind info for stuff in the TEXT segment without unwind info
 
8396                                 if ( strcmp(atom->getSegment().getName(), "__TEXT") == 0 )
 
8397                                         fUnwindInfoAtom->addUnwindInfo(atom, 0, 0, NULL, NULL, NULL);
 
8401                                 for ( ObjectFile::UnwindInfo::iterator uit = atom->beginUnwind(); uit != atom->endUnwind(); ++uit ) {
 
8402                                         fUnwindInfoAtom->addUnwindInfo(atom, uit->startOffset, uit->unwindInfo, atom->getFDE(), atom->getLSDA(), atom->getPersonalityPointer());
 
8410 template <typename A>
 
8411 void Writer<A>::partitionIntoSections()
 
8413         const bool oneSegmentCommand = (fOptions.outputKind() == Options::kObjectFile);
 
8415         // for every atom, set its sectionInfo object and section offset
 
8416         // build up fSegmentInfos along the way
 
8417         ObjectFile::Section* curSection = (ObjectFile::Section*)(-1);
 
8418         SectionInfo* currentSectionInfo = NULL;
 
8419         SegmentInfo* currentSegmentInfo = NULL;
 
8420         SectionInfo* cstringSectionInfo = NULL;
 
8421         unsigned int sectionIndex = 1;
 
8422         fSegmentInfos.reserve(8);
 
8423         for (unsigned int i=0; i < fAllAtoms->size(); ++i) {
 
8424                 ObjectFile::Atom* atom = (*fAllAtoms)[i];
 
8425                 if ( ((atom->getSection() != curSection) || (curSection==NULL)) 
 
8426                         && ((currentSectionInfo == NULL) 
 
8427                                 || (strcmp(atom->getSectionName(),currentSectionInfo->fSectionName) != 0) 
 
8428                                 || (strcmp(atom->getSegment().getName(),currentSectionInfo->fSegmentName) != 0)) ) {
 
8429                         if ( oneSegmentCommand ) {
 
8430                                 if ( currentSegmentInfo == NULL ) {
 
8431                                         currentSegmentInfo = new SegmentInfo(fOptions.segmentAlignment());
 
8432                                         currentSegmentInfo->fInitProtection = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
 
8433                                         currentSegmentInfo->fMaxProtection = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
 
8434                                         this->fSegmentInfos.push_back(currentSegmentInfo);
 
8436                                 currentSectionInfo = new SectionInfo();
 
8437                                 strcpy(currentSectionInfo->fSectionName, atom->getSectionName());
 
8438                                 strcpy(currentSectionInfo->fSegmentName, atom->getSegment().getName());
 
8439                                 currentSectionInfo->fAlignment = atom->getAlignment().powerOf2;
 
8440                                 currentSectionInfo->fAllZeroFill = atom->isZeroFill();
 
8441                                 currentSectionInfo->fVirtualSection = (currentSectionInfo->fSectionName[0] == '.');
 
8442                                 if ( !currentSectionInfo->fVirtualSection || fEmitVirtualSections )
 
8443                                         currentSectionInfo->setIndex(sectionIndex++);
 
8444                                 currentSegmentInfo->fSections.push_back(currentSectionInfo);
 
8445                                 if ( (strcmp(currentSectionInfo->fSegmentName, "__TEXT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__cstring") == 0) ) 
 
8446                                         cstringSectionInfo = currentSectionInfo;
 
8449                                 if ( (currentSegmentInfo == NULL) || (strcmp(currentSegmentInfo->fName, atom->getSegment().getName()) != 0) ) {
 
8450                                         currentSegmentInfo = new SegmentInfo(fOptions.segmentAlignment());
 
8451                                         strcpy(currentSegmentInfo->fName, atom->getSegment().getName());
 
8452                                         uint32_t initprot  = 0;
 
8453                                         if ( atom->getSegment().isContentReadable() )
 
8454                                                 initprot |= VM_PROT_READ;
 
8455                                         if ( atom->getSegment().isContentWritable() )
 
8456                                                 initprot |= VM_PROT_WRITE;
 
8457                                         if ( atom->getSegment().isContentExecutable() )
 
8458                                                 initprot |= VM_PROT_EXECUTE;
 
8459                                         if ( fOptions.readOnlyx86Stubs() && (strcmp(atom->getSegment().getName(), "__IMPORT") == 0) )
 
8460                                                 initprot &= ~VM_PROT_WRITE;     // hack until i386 __pointers section is synthesized by linker
 
8461                                         currentSegmentInfo->fInitProtection = initprot;
 
8462                                         if ( initprot == 0 )
 
8463                                                 currentSegmentInfo->fMaxProtection = 0;  // pagezero should have maxprot==initprot==0
 
8464                                         else if ( fOptions.architecture() == CPU_TYPE_ARM )
 
8465                                                 currentSegmentInfo->fMaxProtection = currentSegmentInfo->fInitProtection; // iPhoneOS wants max==init
 
8467                                                 currentSegmentInfo->fMaxProtection = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
 
8468                                         std::vector<Options::SegmentProtect>& customSegProtections = fOptions.customSegmentProtections();
 
8469                                         for(std::vector<Options::SegmentProtect>::iterator it = customSegProtections.begin(); it != customSegProtections.end(); ++it) {
 
8470                                                 if ( strcmp(it->name, currentSegmentInfo->fName) == 0 ) {
 
8471                                                         currentSegmentInfo->fInitProtection = it->init;
 
8472                                                         currentSegmentInfo->fMaxProtection = it->max;
 
8475                                         currentSegmentInfo->fBaseAddress = atom->getSegment().getBaseAddress();
 
8476                                         currentSegmentInfo->fFixedAddress = atom->getSegment().hasFixedAddress();
 
8477                                         if ( currentSegmentInfo->fFixedAddress && (&(atom->getSegment()) == &Segment::fgStackSegment) )
 
8478                                                 currentSegmentInfo->fIndependentAddress = true;
 
8479                                         if ( (fOptions.outputKind() == Options::kPreload) && (strcmp(currentSegmentInfo->fName, "__LINKEDIT")==0) )
 
8480                                                 currentSegmentInfo->fHasLoadCommand = false;
 
8481                                         if ( strcmp(currentSegmentInfo->fName, "__HEADER")==0 )
 
8482                                                 currentSegmentInfo->fHasLoadCommand = false;
 
8483                                         this->fSegmentInfos.push_back(currentSegmentInfo);
 
8485                                 currentSectionInfo = new SectionInfo();
 
8486                                 currentSectionInfo->fAtoms.reserve(fAllAtoms->size()/4); // reduce reallocations by starting large
 
8487                                 strcpy(currentSectionInfo->fSectionName, atom->getSectionName());
 
8488                                 strcpy(currentSectionInfo->fSegmentName, atom->getSegment().getName());
 
8489                                 currentSectionInfo->fAlignment = atom->getAlignment().powerOf2;
 
8490                                 // check for -sectalign override
 
8491                                 std::vector<Options::SectionAlignment>& alignmentOverrides = fOptions.sectionAlignments();
 
8492                                 for(std::vector<Options::SectionAlignment>::iterator it=alignmentOverrides.begin(); it != alignmentOverrides.end(); ++it) {
 
8493                                         if ( (strcmp(it->segmentName, currentSectionInfo->fSegmentName) == 0) && (strcmp(it->sectionName, currentSectionInfo->fSectionName) == 0) )
 
8494                                                 currentSectionInfo->fAlignment = it->alignment;
 
8496                                 currentSectionInfo->fAllZeroFill = atom->isZeroFill();
 
8497                                 currentSectionInfo->fVirtualSection = ( currentSectionInfo->fSectionName[0] == '.');
 
8498                                 if ( !currentSectionInfo->fVirtualSection || fEmitVirtualSections )
 
8499                                         currentSectionInfo->setIndex(sectionIndex++);
 
8500                                 currentSegmentInfo->fSections.push_back(currentSectionInfo);
 
8502                         //fprintf(stderr, "new section %s for atom %s\n", atom->getSectionName(), atom->getDisplayName());
 
8503                         if ( strcmp(currentSectionInfo->fSectionName, "._load_commands") == 0 ) {
 
8504                                 fLoadCommandsSection = currentSectionInfo;
 
8505                                 fLoadCommandsSegment = currentSegmentInfo;
 
8507                         switch ( atom->getContentType() ) {
 
8508                                 case ObjectFile::Atom::kLazyPointer:
 
8509                                         currentSectionInfo->fAllLazyPointers = true;
 
8510                                         fSymbolTableCommands->needDynamicTable();
 
8512                                 case ObjectFile::Atom::kNonLazyPointer:
 
8513                                         currentSectionInfo->fAllNonLazyPointers = true;
 
8514                                         fSymbolTableCommands->needDynamicTable();
 
8516                                 case ObjectFile::Atom::kLazyDylibPointer:
 
8517                                         currentSectionInfo->fAllLazyDylibPointers = true;
 
8519                                 case ObjectFile::Atom::kStubHelper:
 
8520                                         currentSectionInfo->fAllStubHelpers = true;
 
8522                                 case ObjectFile::Atom::kCFIType:
 
8523                                         currentSectionInfo->fAlignment = __builtin_ctz(sizeof(pint_t)); // always start CFI info pointer aligned
 
8525                                 case ObjectFile::Atom::kStub:
 
8526                                         if ( (strcmp(currentSectionInfo->fSegmentName, "__IMPORT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__jump_table") == 0) ) {
 
8527                                                 currentSectionInfo->fAllSelfModifyingStubs = true;
 
8528                                                 currentSectionInfo->fAlignment = 6; // force x86 fast stubs to start on 64-byte boundary
 
8531                                                 currentSectionInfo->fAllStubs = true;
 
8533                                         fSymbolTableCommands->needDynamicTable();
 
8538                         curSection = atom->getSection();
 
8540                 // any non-zero fill atoms make whole section marked not-zero-fill
 
8541                 if ( currentSectionInfo->fAllZeroFill && ! atom->isZeroFill() )
 
8542                         currentSectionInfo->fAllZeroFill = false;
 
8543                 // change section object to be Writer's SectionInfo object
 
8544                 atom->setSection(currentSectionInfo);
 
8545                 // section alignment is that of a contained atom with the greatest alignment
 
8546                 uint8_t atomAlign = atom->getAlignment().powerOf2;
 
8547                 if ( currentSectionInfo->fAlignment < atomAlign ) 
 
8548                         currentSectionInfo->fAlignment = atomAlign;
 
8549                 // calculate section offset for this atom
 
8550                 uint64_t offset = currentSectionInfo->fSize;
 
8551                 uint64_t alignment = 1 << atomAlign;
 
8552                 uint64_t currentModulus = (offset % alignment);
 
8553                 uint64_t requiredModulus = atom->getAlignment().modulus;
 
8554                 if ( currentModulus != requiredModulus ) {
 
8555                         if ( requiredModulus > currentModulus )
 
8556                                 offset += requiredModulus-currentModulus;
 
8558                                 offset += requiredModulus+alignment-currentModulus;             
 
8560                 atom->setSectionOffset(offset);
 
8561                 uint64_t curAtomSize = atom->getSize();
 
8562                 currentSectionInfo->fSize = offset + curAtomSize;
 
8563                 // add atom to section vector
 
8564                 currentSectionInfo->fAtoms.push_back(atom);
 
8565                 //fprintf(stderr, "  adding atom %p %s size=0x%0llX to section %p %s from %s\n", atom, atom->getDisplayName(), atom->getSize(),
 
8566                 //                              currentSectionInfo, currentSectionInfo->fSectionName, atom->getFile()->getPath());
 
8567                 // update largest size
 
8568                 if ( !currentSectionInfo->fAllZeroFill && (curAtomSize > fLargestAtomSize) )
 
8569                         fLargestAtomSize = curAtomSize;
 
8571         if ( (cstringSectionInfo != NULL) && (cstringSectionInfo->fAlignment > 0) ) {
 
8572                 // when merging cstring sections in .o files, all strings need to use the max alignment
 
8573                 uint64_t offset = 0;
 
8574                 uint64_t cstringAlignment = 1 << cstringSectionInfo->fAlignment;
 
8575                 for (std::vector<ObjectFile::Atom*>::iterator it=cstringSectionInfo->fAtoms.begin(); it != cstringSectionInfo->fAtoms.end(); it++) {
 
8576                         offset = (offset + (cstringAlignment-1)) & (-cstringAlignment);
 
8577                         ObjectFile::Atom* atom = *it;
 
8578                         atom->setSectionOffset(offset);
 
8579                         offset += atom->getSize();
 
8581                 cstringSectionInfo->fSize = offset;
 
8586 struct TargetAndOffset { ObjectFile::Atom* atom; uint32_t offset; };
 
8587 class TargetAndOffsetComparor
 
8590         bool operator()(const TargetAndOffset& left, const TargetAndOffset& right) const
 
8592                 if ( left.atom != right.atom )
 
8593                         return ( left.atom < right.atom );
 
8594                 return ( left.offset < right.offset );
 
8599 bool Writer<ppc>::addBranchIslands()
 
8601         return this->createBranchIslands();
 
8605 bool Writer<ppc64>::addBranchIslands()
 
8607         return this->createBranchIslands();
 
8611 bool Writer<x86>::addBranchIslands()
 
8613         // x86 branches can reach entire 4G address space, so no need for branch islands
 
8618 bool Writer<x86_64>::addBranchIslands()
 
8620         // x86 branches can reach entire 4G size of largest image
 
8625 bool Writer<arm>::addBranchIslands()
 
8627         return this->createBranchIslands();
 
8631 bool Writer<ppc>::isBranchThatMightNeedIsland(uint8_t kind)
 
8634                 case ppc::kBranch24:
 
8635                 case ppc::kBranch24WeakImport:
 
8642 bool Writer<ppc64>::isBranchThatMightNeedIsland(uint8_t kind)
 
8645                 case ppc64::kBranch24:
 
8646                 case ppc64::kBranch24WeakImport:
 
8653 bool Writer<arm>::isBranchThatMightNeedIsland(uint8_t kind)
 
8656                 case arm::kBranch24:
 
8657                 case arm::kBranch24WeakImport:
 
8658                 case arm::kThumbBranch22:
 
8659                 case arm::kThumbBranch22WeakImport:
 
8666 uint32_t Writer<ppc>::textSizeWhenMightNeedBranchIslands() 
 
8672 uint32_t Writer<ppc64>::textSizeWhenMightNeedBranchIslands() 
 
8678 uint32_t Writer<arm>::textSizeWhenMightNeedBranchIslands() 
 
8680         if ( fHasThumbBranches == false )
 
8681                 return 32000000;  // ARM can branch +/- 32MB
 
8682         else if ( fOptions.preferSubArchitecture() && fOptions.subArchitecture() == CPU_SUBTYPE_ARM_V7 ) 
 
8683                 return 16000000;  // thumb2 can branch +/- 16MB
 
8685                 return  4000000;  // thumb1 can branch +/- 4MB
 
8689 uint32_t Writer<ppc>::maxDistanceBetweenIslands() 
 
8691         return 14*1024*1024;
 
8695 uint32_t Writer<ppc64>::maxDistanceBetweenIslands() 
 
8697         return 14*1024*1024;
 
8701 uint32_t Writer<arm>::maxDistanceBetweenIslands() 
 
8703         if ( fHasThumbBranches == false )
 
8704                 return 30*1024*1024;
 
8705         else if ( fOptions.preferSubArchitecture() && fOptions.subArchitecture() == CPU_SUBTYPE_ARM_V7 ) 
 
8706                 return 14*1024*1024;
 
8713 // PowerPC can do PC relative branches as far as +/-16MB.
 
8714 // If a branch target is >16MB then we insert one or more
 
8715 // "branch islands" between the branch and its target that
 
8716 // allows island hopping to the target.
 
8718 // Branch Island Algorithm
 
8720 // If the __TEXT segment < 16MB, then no branch islands needed
 
8721 // Otherwise, every 14MB into the __TEXT segment a region is
 
8722 // added which can contain branch islands.  Every out-of-range
 
8723 // bl instruction is checked.  If it crosses a region, an island
 
8724 // is added to that region with the same target and the bl is
 
8725 // adjusted to target the island instead.
 
8727 // In theory, if too many islands are added to one region, it
 
8728 // could grow the __TEXT enough that other previously in-range
 
8729 // bl branches could be pushed out of range.  We reduce the
 
8730 // probability this could happen by placing the ranges every
 
8731 // 14MB which means the region would have to be 2MB (512,000 islands)
 
8732 // before any branches could be pushed out of range.
 
8734 template <typename A>
 
8735 bool Writer<A>::createBranchIslands()
 
8738         bool result = false;
 
8739         // Can only possibly need branch islands if __TEXT segment > 16M
 
8740         if ( fLoadCommandsSegment->fSize > textSizeWhenMightNeedBranchIslands() ) {
 
8741                 if ( log) fprintf(stderr, "ld: checking for branch islands, __TEXT segment size=%llu\n", fLoadCommandsSegment->fSize);
 
8742                 const uint32_t kBetweenRegions = maxDistanceBetweenIslands(); // place regions of islands every 14MB in __text section
 
8743                 SectionInfo* textSection = NULL;
 
8744                 for (std::vector<SectionInfo*>::iterator it=fLoadCommandsSegment->fSections.begin(); it != fLoadCommandsSegment->fSections.end(); it++) {
 
8745                         if ( strcmp((*it)->fSectionName, "__text") == 0 ) {
 
8747                                 if ( log) fprintf(stderr, "ld: checking for branch islands, __text section size=%llu\n", textSection->fSize);
 
8751                 const int kIslandRegionsCount = fLoadCommandsSegment->fSize / kBetweenRegions;
 
8752                 typedef std::map<TargetAndOffset,ObjectFile::Atom*, TargetAndOffsetComparor> AtomToIsland;
 
8753                 AtomToIsland regionsMap[kIslandRegionsCount];
 
8754                 std::vector<ObjectFile::Atom*> regionsIslands[kIslandRegionsCount];
 
8755                 unsigned int islandCount = 0;
 
8756                 if (log) fprintf(stderr, "ld: will use %u branch island regions\n", kIslandRegionsCount);
 
8758                 // create islands for branch references that are out of range
 
8759                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
8760                         ObjectFile::Atom* atom = *it;
 
8761                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
8762                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
8763                                 ObjectFile::Reference* ref = *rit;
 
8764                                 if ( this->isBranchThatMightNeedIsland(ref->getKind()) ) {
 
8765                                         ObjectFile::Atom& target = ref->getTarget();
 
8766                                         int64_t srcAddr = atom->getAddress() + ref->getFixUpOffset();
 
8767                                         int64_t dstAddr = target.getAddress() + ref->getTargetOffset();
 
8768                                         int64_t displacement = dstAddr - srcAddr;
 
8769                                         TargetAndOffset finalTargetAndOffset = { &target, ref->getTargetOffset() };
 
8770                                         const int64_t kBranchLimit = kBetweenRegions;
 
8771                                         if ( displacement > kBranchLimit ) {
 
8772                                                 // create forward branch chain
 
8773                                                 ObjectFile::Atom* nextTarget = ⌖
 
8774                                                 for (int i=kIslandRegionsCount-1; i >=0 ; --i) {
 
8775                                                         AtomToIsland* region = ®ionsMap[i];
 
8776                                                         int64_t islandRegionAddr = kBetweenRegions * (i+1) + textSection->getBaseAddress();
 
8777                                                         if ( (srcAddr < islandRegionAddr) && (islandRegionAddr <= dstAddr) ) { 
 
8778                                                                 AtomToIsland::iterator pos = region->find(finalTargetAndOffset);
 
8779                                                                 if ( pos == region->end() ) {
 
8780                                                                         BranchIslandAtom<A>* island = new BranchIslandAtom<A>(*this, target.getDisplayName(), i, *nextTarget, *finalTargetAndOffset.atom, finalTargetAndOffset.offset);
 
8781                                                                         island->setSection(textSection);
 
8782                                                                         (*region)[finalTargetAndOffset] = island;
 
8783                                                                         if (log) fprintf(stderr, "added island %s to region %d for %s\n", island->getDisplayName(), i, atom->getDisplayName());
 
8784                                                                         regionsIslands[i].push_back(island);
 
8786                                                                         nextTarget = island;
 
8789                                                                         nextTarget = pos->second;
 
8793                                                 if (log) fprintf(stderr, "using island %s for branch to %s from %s\n", nextTarget->getDisplayName(), target.getDisplayName(), atom->getDisplayName());
 
8794                                                 ref->setTarget(*nextTarget, 0);
 
8796                                         else if ( displacement < (-kBranchLimit) ) {
 
8797                                                 // create back branching chain
 
8798                                                 ObjectFile::Atom* prevTarget = ⌖
 
8799                                                 for (int i=0; i < kIslandRegionsCount ; ++i) {
 
8800                                                         AtomToIsland* region = ®ionsMap[i];
 
8801                                                         int64_t islandRegionAddr = kBetweenRegions * (i+1);
 
8802                                                         if ( (dstAddr <= islandRegionAddr) && (islandRegionAddr < srcAddr) ) {
 
8803                                                                 AtomToIsland::iterator pos = region->find(finalTargetAndOffset);
 
8804                                                                 if ( pos == region->end() ) {
 
8805                                                                         BranchIslandAtom<A>* island = new BranchIslandAtom<A>(*this, target.getDisplayName(), i, *prevTarget, *finalTargetAndOffset.atom, finalTargetAndOffset.offset);
 
8806                                                                         island->setSection(textSection);
 
8807                                                                         (*region)[finalTargetAndOffset] = island;
 
8808                                                                         if (log) fprintf(stderr, "added back island %s to region %d for %s\n", island->getDisplayName(), i, atom->getDisplayName());
 
8809                                                                         regionsIslands[i].push_back(island);
 
8811                                                                         prevTarget = island;
 
8814                                                                         prevTarget = pos->second;
 
8818                                                 if (log) fprintf(stderr, "using back island %s for %s\n", prevTarget->getDisplayName(), atom->getDisplayName());
 
8819                                                 ref->setTarget(*prevTarget, 0);
 
8825                 // insert islands into __text section and adjust section offsets
 
8826                 if ( islandCount > 0 ) {
 
8827                         if ( log ) fprintf(stderr, "ld: %u branch islands required in %u regions\n", islandCount, kIslandRegionsCount);
 
8828                         std::vector<ObjectFile::Atom*> newAtomList;
 
8829                         newAtomList.reserve(textSection->fAtoms.size()+islandCount);
 
8830                         uint64_t islandRegionAddr = kBetweenRegions + textSection->getBaseAddress();
 
8831                         uint64_t textSectionAlignment = (1 << textSection->fAlignment);
 
8832                         int regionIndex = 0;
 
8833                         uint64_t atomSlide = 0;
 
8834                         uint64_t sectionOffset = 0;
 
8835                         for (std::vector<ObjectFile::Atom*>::iterator it=textSection->fAtoms.begin(); it != textSection->fAtoms.end(); it++) {
 
8836                                 ObjectFile::Atom* atom = *it;
 
8837                                 if ( (atom->getAddress()+atom->getSize()) > islandRegionAddr ) {
 
8838                                         uint64_t islandStartOffset = atom->getSectionOffset() + atomSlide;
 
8839                                         sectionOffset = islandStartOffset;
 
8840                                         std::vector<ObjectFile::Atom*>* regionIslands = ®ionsIslands[regionIndex];
 
8841                                         for (std::vector<ObjectFile::Atom*>::iterator rit=regionIslands->begin(); rit != regionIslands->end(); rit++) {
 
8842                                                 ObjectFile::Atom* islandAtom = *rit;
 
8843                                                 newAtomList.push_back(islandAtom);
 
8844                                                 uint64_t alignment = 1 << (islandAtom->getAlignment().powerOf2);
 
8845                                                 sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
 
8846                                                 islandAtom->setSectionOffset(sectionOffset);
 
8847                                                 if ( log ) fprintf(stderr, "assigning  __text offset 0x%08llx to %s\n", sectionOffset, islandAtom->getDisplayName());
 
8848                                                 sectionOffset += islandAtom->getSize();
 
8851                                         islandRegionAddr += kBetweenRegions;
 
8852                                         uint64_t islandRegionAlignmentBlocks = (sectionOffset - islandStartOffset + textSectionAlignment - 1) / textSectionAlignment;
 
8853                                         atomSlide += (islandRegionAlignmentBlocks * textSectionAlignment);
 
8855                                 newAtomList.push_back(atom);
 
8856                                 if ( atomSlide != 0 )
 
8857                                         atom->setSectionOffset(atom->getSectionOffset()+atomSlide);
 
8859                         sectionOffset = textSection->fSize+atomSlide;
 
8860                         // put any remaining islands at end of __text section
 
8861                         if ( regionIndex < kIslandRegionsCount ) {
 
8862                                 std::vector<ObjectFile::Atom*>* regionIslands = ®ionsIslands[regionIndex];
 
8863                                 for (std::vector<ObjectFile::Atom*>::iterator rit=regionIslands->begin(); rit != regionIslands->end(); rit++) {
 
8864                                         ObjectFile::Atom* islandAtom = *rit;
 
8865                                         newAtomList.push_back(islandAtom);
 
8866                                         uint64_t alignment = 1 << (islandAtom->getAlignment().powerOf2);
 
8867                                         sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
 
8868                                         islandAtom->setSectionOffset(sectionOffset);
 
8869                                         if ( log ) fprintf(stderr, "assigning  __text offset 0x%08llx to %s\n", sectionOffset, islandAtom->getDisplayName());
 
8870                                         sectionOffset += islandAtom->getSize();
 
8874                         textSection->fAtoms = newAtomList;
 
8875                         textSection->fSize = sectionOffset;
 
8884 template <typename A>
 
8885 void Writer<A>::adjustLoadCommandsAndPadding()
 
8887         fSegmentCommands->computeSize();
 
8889         // recompute load command section offsets
 
8890         uint64_t offset = 0;
 
8891         std::vector<class ObjectFile::Atom*>& loadCommandAtoms = fLoadCommandsSection->fAtoms;
 
8892         const unsigned int atomCount = loadCommandAtoms.size();
 
8893         for (unsigned int i=0; i < atomCount; ++i) {
 
8894                 ObjectFile::Atom* atom = loadCommandAtoms[i];
 
8895                 uint64_t alignment = 1 << atom->getAlignment().powerOf2;
 
8896                 offset = ( (offset+alignment-1) & (-alignment) );
 
8897                 atom->setSectionOffset(offset);
 
8898                 uint32_t atomSize = atom->getSize();
 
8899                 if ( atomSize > fLargestAtomSize )
 
8900                         fLargestAtomSize = atomSize;
 
8902                 fLoadCommandsSection->fSize = offset;
 
8904         const uint32_t sizeOfLoadCommandsPlusHeader = offset + sizeof(macho_header<typename A::P>);
 
8906         std::vector<SectionInfo*>& sectionInfos = fLoadCommandsSegment->fSections;
 
8907         const int sectionCount = sectionInfos.size();
 
8908         uint32_t totalSizeOfTEXTLessHeaderAndLoadCommands = 0;
 
8909         for(int j=0; j < sectionCount; ++j) {
 
8910                 SectionInfo* curSection = sectionInfos[j];
 
8911                 if ( strcmp(curSection->fSectionName, fHeaderPadding->getSectionName()) == 0 )
 
8913                 totalSizeOfTEXTLessHeaderAndLoadCommands += curSection->fSize;
 
8915         uint64_t paddingSize = 0;
 
8916         if ( fOptions.outputKind() == Options::kDyld ) {
 
8917                 // dyld itself has special padding requirements.  We want the beginning __text section to start at a stable address
 
8918                 paddingSize = 4096 - (totalSizeOfTEXTLessHeaderAndLoadCommands % 4096);
 
8920         else if ( fOptions.outputKind() == Options::kObjectFile ) {
 
8921                 // mach-o .o files need no padding between load commands and first section
 
8922                 // but leave enough room that the object file could be signed
 
8925         else if ( fOptions.outputKind() == Options::kPreload ) {
 
8926                 // mach-o MH_PRELOAD files need no padding between load commands and first section
 
8930                 // work backwards from end of segment and lay out sections so that extra room goes to padding atom
 
8932                 for(int j=sectionCount-1; j >=0; --j) {
 
8933                         SectionInfo* curSection = sectionInfos[j];
 
8934                         if ( strcmp(curSection->fSectionName, fHeaderPadding->getSectionName()) == 0 ) {
 
8935                                 addr -= (fLoadCommandsSection->fSize+fMachHeaderAtom->getSize());
 
8936                                 paddingSize = addr % fOptions.segmentAlignment();
 
8939                         addr -= curSection->fSize;
 
8940                         addr = addr & (0 - (1 << curSection->fAlignment));
 
8943                 // if command line requires more padding than this
 
8944                 uint32_t minPad = fOptions.minimumHeaderPad();
 
8945                 if ( fOptions.maxMminimumHeaderPad() ) {
 
8946                         // -headerpad_max_install_names means there should be room for every path load command to grow to 1204 bytes
 
8947                         uint32_t altMin = fLibraryToOrdinal.size() * MAXPATHLEN;
 
8948                         if ( fOptions.outputKind() ==  Options::kDynamicLibrary )
 
8949                                 altMin += MAXPATHLEN;
 
8950                         if ( altMin > minPad )
 
8953                 if ( paddingSize < minPad ) {
 
8954                         int extraPages = (minPad - paddingSize + fOptions.segmentAlignment() - 1)/fOptions.segmentAlignment();
 
8955                         paddingSize += extraPages * fOptions.segmentAlignment();
 
8958                 if ( fOptions.makeEncryptable() ) {
 
8959                         // load commands must be on a separate non-encrypted page
 
8960                         int loadCommandsPage = (sizeOfLoadCommandsPlusHeader + minPad)/fOptions.segmentAlignment();
 
8961                         int textPage = (sizeOfLoadCommandsPlusHeader + paddingSize)/fOptions.segmentAlignment();
 
8962                         if ( loadCommandsPage == textPage ) {
 
8963                                 paddingSize += fOptions.segmentAlignment();
 
8967                         //paddingSize = 4096 - ((totalSizeOfTEXTLessHeaderAndLoadCommands+fOptions.minimumHeaderPad()) % 4096) + fOptions.minimumHeaderPad();
 
8968                         fEncryptionLoadCommand->setStartEncryptionOffset(textPage*fOptions.segmentAlignment());
 
8972         // adjust atom size and update section size
 
8973         fHeaderPadding->setSize(paddingSize);
 
8974         for(int j=0; j < sectionCount; ++j) {
 
8975                 SectionInfo* curSection = sectionInfos[j];
 
8976                 if ( strcmp(curSection->fSectionName, fHeaderPadding->getSectionName()) == 0 )
 
8977                         curSection->fSize = paddingSize;
 
8981 static uint64_t segmentAlign(uint64_t addr, uint64_t alignment) 
 
8983         return ((addr+alignment-1) & (-alignment)); 
 
8986 // assign file offsets and logical address to all segments
 
8987 template <typename A>
 
8988 void Writer<A>::assignFileOffsets()
 
8990         const bool virtualSectionOccupyAddressSpace = ((fOptions.outputKind() != Options::kObjectFile)
 
8991                                                                                                 && (fOptions.outputKind() != Options::kPreload));
 
8992         bool haveFixedSegments = false;
 
8993         uint64_t fileOffset = 0;
 
8994         uint64_t nextContiguousAddress = fOptions.baseAddress();
 
8995         uint64_t nextReadOnlyAddress = fOptions.baseAddress();
 
8996         uint64_t nextWritableAddress = fOptions.baseWritableAddress();
 
8998         // process segments with fixed addresses (-segaddr)
 
8999         for (std::vector<Options::SegmentStart>::iterator it = fOptions.customSegmentAddresses().begin(); it != fOptions.customSegmentAddresses().end(); ++it) {
 
9000                         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
9001                         SegmentInfo* curSegment = *segit;
 
9002                         if ( strcmp(curSegment->fName, it->name) == 0 ) {
 
9003                                 curSegment->fBaseAddress = it->address;
 
9004                                 curSegment->fFixedAddress = true;
 
9010         // process segments with fixed addresses (-seg_page_size)
 
9011         for (std::vector<Options::SegmentSize>::iterator it = fOptions.customSegmentSizes().begin(); it != fOptions.customSegmentSizes().end(); ++it) {
 
9012                         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
9013                         SegmentInfo* curSegment = *segit;
 
9014                         if ( strcmp(curSegment->fName, it->name) == 0 ) {
 
9015                                 curSegment->fPageSize = it->size;
 
9021         // Run through the segments and each segment's sections to assign addresses
 
9022         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
9023                 SegmentInfo* curSegment = *segit;
 
9025                 if ( fOptions.splitSeg() ) {
 
9026                         if ( curSegment->fInitProtection & VM_PROT_WRITE ) 
 
9027                                 nextContiguousAddress = nextWritableAddress;
 
9029                                 nextContiguousAddress = nextReadOnlyAddress;
 
9032                 if ( fOptions.outputKind() == Options::kPreload ) {
 
9033                         if ( strcmp(curSegment->fName, "__HEADER") == 0 ) 
 
9034                                 nextContiguousAddress = 0;
 
9035                         else if ( strcmp(curSegment->fName, "__TEXT") == 0 ) 
 
9036                                 nextContiguousAddress = fOptions.baseAddress();
 
9039                 fileOffset = segmentAlign(fileOffset, curSegment->fPageSize);
 
9040                 curSegment->fFileOffset = fileOffset;
 
9042                 // Set the segment base address
 
9043                 if ( curSegment->fFixedAddress )
 
9044                         haveFixedSegments = true;
 
9046                         curSegment->fBaseAddress = segmentAlign(nextContiguousAddress, curSegment->fPageSize);
 
9048                 // We've set the segment address, now run through each section.
 
9049                 uint64_t address = curSegment->fBaseAddress;
 
9050                 SectionInfo* firstZeroFillSection = NULL;
 
9051                 SectionInfo* prevSection = NULL;
 
9053                 std::vector<SectionInfo*>& sectionInfos = curSegment->fSections;
 
9055                 for (std::vector<SectionInfo*>::iterator it = sectionInfos.begin(); it != sectionInfos.end(); ++it) {
 
9056                         SectionInfo* curSection = *it;
 
9058                         // adjust section address based on alignment
 
9059                         uint64_t alignment = 1 << curSection->fAlignment;
 
9060                         if ( curSection->fAtoms.size() == 1 ) {
 
9061                                 // if there is only one atom in section, use modulus for even better layout
 
9062                                 ObjectFile::Alignment atomAlign = curSection->fAtoms[0]->getAlignment();
 
9063                                 uint64_t atomAlignP2 = (1 << atomAlign.powerOf2);
 
9064                                 uint64_t currentModulus = (address % atomAlignP2);
 
9065                                 if ( currentModulus != atomAlign.modulus ) {
 
9066                                         if ( atomAlign.modulus > currentModulus )
 
9067                                                 address += atomAlign.modulus-currentModulus;
 
9069                                                 address += atomAlign.modulus+atomAlignP2-currentModulus;                
 
9073                                 address = ( (address+alignment-1) & (-alignment) );
 
9075                         // adjust file offset to match address
 
9076                         if ( prevSection != NULL ) {
 
9077                                 if ( virtualSectionOccupyAddressSpace || !prevSection->fVirtualSection )
 
9078                                         fileOffset = (address - prevSection->getBaseAddress()) + prevSection->fFileOffset;
 
9080                                         fileOffset = ( (fileOffset+alignment-1) & (-alignment) );
 
9083                         // update section info
 
9084                         curSection->fFileOffset = fileOffset;
 
9085                         curSection->setBaseAddress(address);
 
9086                         //fprintf(stderr, "%s %s addr=0x%llX, fileoffset=0x%llX, size=0x%llX\n", curSegment->fName, curSection->fSectionName, address, fileOffset, curSection->fSize);
 
9088                         // keep track of trailing zero fill sections
 
9089                         if ( curSection->fAllZeroFill && (firstZeroFillSection == NULL) )
 
9090                                 firstZeroFillSection = curSection;
 
9091                         if ( !curSection->fAllZeroFill && (firstZeroFillSection != NULL) && (fOptions.outputKind() != Options::kObjectFile) ) 
 
9092                                 throwf("zero-fill section %s not at end of segment", curSection->fSectionName);
 
9094                         // update running pointers
 
9095                         if ( virtualSectionOccupyAddressSpace || !curSection->fVirtualSection )
 
9096                                 address += curSection->fSize;
 
9097                         fileOffset += curSection->fSize;
 
9099                         // sanity check size of 32-bit binaries
 
9100                         if ( address > maxAddress() )
 
9101                                 throwf("section %s exceeds 4GB limit", curSection->fSectionName);
 
9103                         // update segment info
 
9104                         curSegment->fFileSize = fileOffset - curSegment->fFileOffset;
 
9105                         curSegment->fSize = curSegment->fFileSize;
 
9106                         prevSection = curSection;
 
9109                 if ( fOptions.outputKind() == Options::kObjectFile ) {
 
9110                         // don't page align .o files
 
9113                         // optimize trailing zero-fill sections to not occupy disk space
 
9114                         if ( firstZeroFillSection != NULL ) {
 
9115                                 curSegment->fFileSize = firstZeroFillSection->fFileOffset - curSegment->fFileOffset;
 
9116                                 fileOffset = firstZeroFillSection->fFileOffset;
 
9118                         // page align segment size
 
9119                         curSegment->fFileSize = segmentAlign(curSegment->fFileSize, curSegment->fPageSize);
 
9120                         curSegment->fSize         = segmentAlign(curSegment->fSize, curSegment->fPageSize);
 
9121                         if ( !curSegment->fIndependentAddress && (curSegment->fBaseAddress >= nextContiguousAddress) ) {
 
9122                                 nextContiguousAddress = segmentAlign(curSegment->fBaseAddress+curSegment->fSize, curSegment->fPageSize);
 
9123                                 fileOffset = segmentAlign(fileOffset, curSegment->fPageSize);
 
9124                                 if ( curSegment->fInitProtection & VM_PROT_WRITE )
 
9125                                         nextWritableAddress = nextContiguousAddress;
 
9127                                         nextReadOnlyAddress = nextContiguousAddress;
 
9130                 //fprintf(stderr, "end of seg %s, fileoffset=0x%llX, nextContiguousAddress=0x%llX\n", curSegment->fName, fileOffset, nextContiguousAddress);
 
9133         // check for segment overlaps caused by user specified fixed segments (e.g. __PAGEZERO, __UNIXSTACK)
 
9134         if ( haveFixedSegments ) {
 
9135                 int segCount = fSegmentInfos.size();
 
9136                 for(int i=0; i < segCount; ++i) {
 
9137                         SegmentInfo* segment1 = fSegmentInfos[i];
 
9139                         for(int j=0; j < segCount; ++j) {
 
9141                                         SegmentInfo* segment2 = fSegmentInfos[j];
 
9143                                         if ( segment1->fBaseAddress < segment2->fBaseAddress ) {
 
9144                                                 if ( (segment1->fBaseAddress+segment1->fSize) > segment2->fBaseAddress )
 
9145                                                         throwf("segments overlap: %s (0x%08llX + 0x%08llX) and %s (0x%08llX + 0x%08llX)",
 
9146                                                                 segment1->fName, segment1->fBaseAddress, segment1->fSize, segment2->fName, segment2->fBaseAddress, segment2->fSize);
 
9148                                         else if ( segment1->fBaseAddress > segment2->fBaseAddress ) {
 
9149                                                 if ( (segment2->fBaseAddress+segment2->fSize) > segment1->fBaseAddress )
 
9150                                                         throwf("segments overlap: %s (0x%08llX + 0x%08llX) and %s (0x%08llX + 0x%08llX)",
 
9151                                                                 segment1->fName, segment1->fBaseAddress, segment1->fSize, segment2->fName, segment2->fBaseAddress, segment2->fSize);
 
9153                                         else if ( (segment1->fSize != 0) && (segment2->fSize != 0) ) {
 
9154                                                         throwf("segments overlap: %s (0x%08llX + 0x%08llX) and %s (0x%08llX + 0x%08llX)",
 
9155                                                                 segment1->fName, segment1->fBaseAddress, segment1->fSize, segment2->fName, segment2->fBaseAddress, segment2->fSize);
 
9162         // set up fFirstWritableSegment and fWritableSegmentPastFirst4GB
 
9163         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
9164                 SegmentInfo* curSegment = *segit;
 
9165                 if ( (curSegment->fInitProtection & VM_PROT_WRITE) != 0 ) {
 
9166                         if ( fFirstWritableSegment == NULL )
 
9167                                 fFirstWritableSegment = curSegment;
 
9168                         if ( (curSegment->fBaseAddress + curSegment->fSize - fOptions.baseAddress()) >= 0x100000000LL )
 
9169                                 fWritableSegmentPastFirst4GB = true;
 
9173         // record size of encrypted part of __TEXT segment
 
9174         if ( fOptions.makeEncryptable() ) {
 
9175                 for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
9176                         SegmentInfo* curSegment = *segit;
 
9177                         if ( strcmp(curSegment->fName, "__TEXT") == 0 ) {
 
9178                                 fEncryptionLoadCommand->setEndEncryptionOffset(curSegment->fFileSize);
 
9186 template <typename A>
 
9187 void Writer<A>::adjustLinkEditSections()
 
9189         // link edit content is always in last segment
 
9190         SegmentInfo* lastSeg = fSegmentInfos[fSegmentInfos.size()-1];
 
9191         unsigned int firstLinkEditSectionIndex = 0;
 
9192         while ( strcmp(lastSeg->fSections[firstLinkEditSectionIndex]->fSegmentName, "__LINKEDIT") != 0 )
 
9193                 ++firstLinkEditSectionIndex;
 
9195         const unsigned int linkEditSectionCount = lastSeg->fSections.size();
 
9196         uint64_t fileOffset = lastSeg->fSections[firstLinkEditSectionIndex]->fFileOffset;
 
9197         uint64_t address = lastSeg->fSections[firstLinkEditSectionIndex]->getBaseAddress();
 
9198         if ( fPadSegmentInfo != NULL ) {
 
9199                 // insert __4GBFILL segment into segments vector before LINKEDIT
 
9200                 for(std::vector<SegmentInfo*>::iterator it = fSegmentInfos.begin(); it != fSegmentInfos.end(); ++it) {
 
9201                         if ( *it == lastSeg ) {
 
9202                                 fSegmentInfos.insert(it, fPadSegmentInfo);
 
9206                 // adjust  __4GBFILL segment to span from end of last segment to zeroPageSize
 
9207                 fPadSegmentInfo->fSize = fOptions.zeroPageSize() - address;
 
9208                 fPadSegmentInfo->fBaseAddress = address;
 
9209                 // adjust LINKEDIT to start at zeroPageSize
 
9210                 address = fOptions.zeroPageSize();
 
9211                 lastSeg->fBaseAddress = fOptions.zeroPageSize();
 
9213         for (unsigned int i=firstLinkEditSectionIndex; i < linkEditSectionCount; ++i) {
 
9214                 std::vector<class ObjectFile::Atom*>& atoms = lastSeg->fSections[i]->fAtoms;
 
9215                 // adjust section address based on alignment
 
9216                 uint64_t sectionAlignment = 1 << lastSeg->fSections[i]->fAlignment;
 
9217                 uint64_t pad = ((address+sectionAlignment-1) & (-sectionAlignment)) - address;
 
9219                 fileOffset += pad;      // adjust file offset to match address
 
9220                 lastSeg->fSections[i]->setBaseAddress(address);
 
9221                 if ( strcmp(lastSeg->fSections[i]->fSectionName, "._absolute") == 0 )
 
9222                         lastSeg->fSections[i]->setBaseAddress(0);
 
9223                 lastSeg->fSections[i]->fFileOffset = fileOffset;
 
9224                 uint64_t sectionOffset = 0;
 
9225                 for (unsigned int j=0; j < atoms.size(); ++j) {
 
9226                         ObjectFile::Atom* atom = atoms[j];
 
9227                         uint64_t alignment = 1 << atom->getAlignment().powerOf2;
 
9228                         sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
 
9229                         atom->setSectionOffset(sectionOffset);
 
9230                         uint64_t size = atom->getSize();
 
9231                         sectionOffset += size;
 
9232                         if ( size > fLargestAtomSize )
 
9233                                 fLargestAtomSize = size;
 
9235                 //fprintf(stderr, "setting: lastSeg->fSections[%d]->fSize = 0x%08llX\n", i, sectionOffset);
 
9236                 lastSeg->fSections[i]->fSize = sectionOffset;
 
9237                 fileOffset += sectionOffset;
 
9238                 address += sectionOffset;
 
9240         if ( fOptions.outputKind() == Options::kObjectFile ) {
 
9241                 //lastSeg->fBaseAddress = 0;
 
9242                 //lastSeg->fSize = lastSeg->fSections[firstLinkEditSectionIndex]->
 
9243                 //lastSeg->fFileOffset = 0;
 
9244                 //lastSeg->fFileSize =
 
9247                 lastSeg->fFileSize = fileOffset - lastSeg->fFileOffset;
 
9248                 lastSeg->fSize     = (address - lastSeg->fBaseAddress+4095) & (-4096);
 
9253 template <typename A>
 
9254 ObjectFile::Atom::Scope MachHeaderAtom<A>::getScope() const
 
9256         switch ( fWriter.fOptions.outputKind() ) {
 
9257                 case Options::kDynamicExecutable:
 
9258                 case Options::kStaticExecutable:
 
9259                         return ObjectFile::Atom::scopeGlobal;
 
9260                 case Options::kDynamicLibrary:
 
9261                 case Options::kDynamicBundle:
 
9262                 case Options::kDyld:
 
9263                 case Options::kObjectFile:
 
9264                 case Options::kPreload:
 
9265                 case Options::kKextBundle:
 
9266                         return ObjectFile::Atom::scopeLinkageUnit;
 
9268         throw "unknown header type";
 
9271 template <typename A>
 
9272 ObjectFile::Atom::SymbolTableInclusion MachHeaderAtom<A>::getSymbolTableInclusion() const
 
9274         switch ( fWriter.fOptions.outputKind() ) {
 
9275                 case Options::kDynamicExecutable:
 
9276                         return ObjectFile::Atom::kSymbolTableInAndNeverStrip;
 
9277                 case Options::kStaticExecutable:
 
9278                         return ObjectFile::Atom::kSymbolTableInAsAbsolute;
 
9279                 case Options::kDynamicLibrary:
 
9280                 case Options::kDynamicBundle:
 
9281                 case Options::kDyld:
 
9282                         return ObjectFile::Atom::kSymbolTableIn;
 
9283                 case Options::kObjectFile:
 
9284                 case Options::kPreload:
 
9285                 case Options::kKextBundle:
 
9286                         return ObjectFile::Atom::kSymbolTableNotIn;
 
9288         throw "unknown header type";
 
9291 template <typename A>
 
9292 const char* MachHeaderAtom<A>::getName() const
 
9294         switch ( fWriter.fOptions.outputKind() ) {
 
9295                 case Options::kDynamicExecutable:
 
9296                 case Options::kStaticExecutable:
 
9297                         return "__mh_execute_header";
 
9298                 case Options::kDynamicLibrary:
 
9299                         return "__mh_dylib_header";
 
9300                 case Options::kDynamicBundle:
 
9301                         return "__mh_bundle_header";
 
9302                 case Options::kObjectFile:
 
9303                 case Options::kPreload:
 
9304                 case Options::kKextBundle:
 
9306                 case Options::kDyld:
 
9307                         return "__mh_dylinker_header";
 
9309         throw "unknown header type";
 
9312 template <typename A>
 
9313 const char* MachHeaderAtom<A>::getDisplayName() const
 
9315         switch ( fWriter.fOptions.outputKind() ) {
 
9316                 case Options::kDynamicExecutable:
 
9317                 case Options::kStaticExecutable:
 
9318                 case Options::kDynamicLibrary:
 
9319                 case Options::kDynamicBundle:
 
9320                 case Options::kDyld:
 
9321                         return this->getName();
 
9322                 case Options::kObjectFile:
 
9323                 case Options::kPreload:
 
9324                 case Options::kKextBundle:
 
9325                         return "mach header";
 
9327         throw "unknown header type";
 
9330 template <typename A>
 
9331 void MachHeaderAtom<A>::copyRawContent(uint8_t buffer[]) const
 
9334         uint32_t fileType = 0;
 
9335         switch ( fWriter.fOptions.outputKind() ) {
 
9336                 case Options::kDynamicExecutable:
 
9337                 case Options::kStaticExecutable:
 
9338                         fileType = MH_EXECUTE;
 
9340                 case Options::kDynamicLibrary:
 
9341                         fileType = MH_DYLIB;
 
9343                 case Options::kDynamicBundle:
 
9344                         fileType = MH_BUNDLE;
 
9346                 case Options::kObjectFile:
 
9347                         fileType = MH_OBJECT;
 
9349                 case Options::kDyld:
 
9350                         fileType = MH_DYLINKER;
 
9352                 case Options::kPreload:
 
9353                         fileType = MH_PRELOAD;
 
9355                 case Options::kKextBundle:
 
9356                         fileType = MH_KEXT_BUNDLE;
 
9362         if ( fWriter.fOptions.outputKind() == Options::kObjectFile ) {
 
9363                 if ( fWriter.fCanScatter )
 
9364                         flags = MH_SUBSECTIONS_VIA_SYMBOLS;
 
9367                 if ( fWriter.fOptions.outputKind() == Options::kStaticExecutable ) {
 
9368                         flags |= MH_NOUNDEFS;
 
9370                 else if ( fWriter.fOptions.outputKind() == Options::kPreload ) {
 
9371                         flags |= MH_NOUNDEFS;
 
9372                         if ( fWriter.fOptions.positionIndependentExecutable() ) 
 
9376                         flags = MH_DYLDLINK;
 
9377                         if ( fWriter.fOptions.bindAtLoad() )
 
9378                                 flags |= MH_BINDATLOAD;
 
9379                         switch ( fWriter.fOptions.nameSpace() ) {
 
9380                                 case Options::kTwoLevelNameSpace:
 
9381                                         flags |= MH_TWOLEVEL | MH_NOUNDEFS;
 
9383                                 case Options::kFlatNameSpace:
 
9385                                 case Options::kForceFlatNameSpace:
 
9386                                         flags |= MH_FORCE_FLAT;
 
9389                         bool hasWeakDefines = fWriter.fHasWeakExports;
 
9390                         if ( fWriter.fRegularDefAtomsThatOverrideADylibsWeakDef->size() != 0 ) {
 
9391                                 for(std::set<const ObjectFile::Atom*>::iterator it = fWriter.fRegularDefAtomsThatOverrideADylibsWeakDef->begin();
 
9392                                                                                                         it != fWriter.fRegularDefAtomsThatOverrideADylibsWeakDef->end(); ++it) {
 
9393                                         if ( fWriter.shouldExport(**it) ) {
 
9394                                                 hasWeakDefines = true;
 
9399                         if ( hasWeakDefines )
 
9400                                 flags |= MH_WEAK_DEFINES;
 
9401                         if ( fWriter.fReferencesWeakImports || fWriter.fHasWeakExports )
 
9402                                 flags |= MH_BINDS_TO_WEAK;
 
9403                         if ( fWriter.fOptions.prebind() )
 
9404                                 flags |= MH_PREBOUND;
 
9405                         if ( fWriter.fOptions.splitSeg() )
 
9406                                 flags |= MH_SPLIT_SEGS;
 
9407                         if ( (fWriter.fOptions.outputKind() == Options::kDynamicLibrary) && fWriter.fNoReExportedDylibs ) 
 
9408                                 flags |= MH_NO_REEXPORTED_DYLIBS;
 
9409                         if ( fWriter.fOptions.positionIndependentExecutable() ) 
 
9411                         if ( fWriter.fOptions.markAutoDeadStripDylib() ) 
 
9412                                 flags |= MH_DEAD_STRIPPABLE_DYLIB;
 
9414                 if ( fWriter.fOptions.hasExecutableStack() )
 
9415                         flags |= MH_ALLOW_STACK_EXECUTION;
 
9416                 if ( fWriter.fOptions.readerOptions().fRootSafe )
 
9417                         flags |= MH_ROOT_SAFE;
 
9418                 if ( fWriter.fOptions.readerOptions().fSetuidSafe )
 
9419                         flags |= MH_SETUID_SAFE;
 
9422         // get commands info
 
9423         uint32_t commandsSize = 0;
 
9424         uint32_t commandsCount = 0;
 
9426         std::vector<class ObjectFile::Atom*>& loadCommandAtoms = fWriter.fLoadCommandsSection->fAtoms;
 
9427         for (std::vector<ObjectFile::Atom*>::iterator it=loadCommandAtoms.begin(); it != loadCommandAtoms.end(); it++) {
 
9428                 ObjectFile::Atom* atom = *it;
 
9429                 commandsSize += atom->getSize();
 
9430                 // segment and symbol table atoms can contain more than one load command
 
9431                 if ( atom == fWriter.fSegmentCommands )
 
9432                         commandsCount += fWriter.fSegmentCommands->commandCount();
 
9433                 else if ( atom == fWriter.fSymbolTableCommands )
 
9434                         commandsCount += fWriter.fSymbolTableCommands->commandCount();
 
9435                 else if ( atom->getSize() != 0 )
 
9439         // fill out mach_header
 
9440         macho_header<typename A::P>* mh = (macho_header<typename A::P>*)buffer;
 
9442         mh->set_filetype(fileType);
 
9443         mh->set_ncmds(commandsCount);
 
9444         mh->set_sizeofcmds(commandsSize);
 
9445         mh->set_flags(flags);
 
9449 void MachHeaderAtom<ppc>::setHeaderInfo(macho_header<ppc::P>& header) const
 
9451         header.set_magic(MH_MAGIC);
 
9452         header.set_cputype(CPU_TYPE_POWERPC);
 
9453     header.set_cpusubtype(fWriter.fCpuConstraint);
 
9457 void MachHeaderAtom<ppc64>::setHeaderInfo(macho_header<ppc64::P>& header) const
 
9459         header.set_magic(MH_MAGIC_64);
 
9460         header.set_cputype(CPU_TYPE_POWERPC64);
 
9461         if ( (fWriter.fOptions.outputKind() == Options::kDynamicExecutable) && (fWriter.fOptions.macosxVersionMin() >= ObjectFile::ReaderOptions::k10_5) )
 
9462                 header.set_cpusubtype(CPU_SUBTYPE_POWERPC_ALL | 0x80000000);
 
9464                 header.set_cpusubtype(CPU_SUBTYPE_POWERPC_ALL);
 
9465         header.set_reserved(0);
 
9469 void MachHeaderAtom<x86>::setHeaderInfo(macho_header<x86::P>& header) const
 
9471         header.set_magic(MH_MAGIC);
 
9472         header.set_cputype(CPU_TYPE_I386);
 
9473         header.set_cpusubtype(CPU_SUBTYPE_I386_ALL);
 
9477 void MachHeaderAtom<x86_64>::setHeaderInfo(macho_header<x86_64::P>& header) const
 
9479         header.set_magic(MH_MAGIC_64);
 
9480         header.set_cputype(CPU_TYPE_X86_64);
 
9481         if ( (fWriter.fOptions.outputKind() == Options::kDynamicExecutable) && (fWriter.fOptions.macosxVersionMin() >= ObjectFile::ReaderOptions::k10_5) )
 
9482                 header.set_cpusubtype(CPU_SUBTYPE_X86_64_ALL | 0x80000000);
 
9484                 header.set_cpusubtype(CPU_SUBTYPE_X86_64_ALL);
 
9485         header.set_reserved(0);
 
9489 void MachHeaderAtom<arm>::setHeaderInfo(macho_header<arm::P>& header) const
 
9491         header.set_magic(MH_MAGIC);
 
9492         header.set_cputype(CPU_TYPE_ARM);
 
9493         header.set_cpusubtype(fWriter.fCpuConstraint);
 
9496 template <typename A>
 
9497 CustomStackAtom<A>::CustomStackAtom(Writer<A>& writer)
 
9498  : WriterAtom<A>(writer, Segment::fgStackSegment)
 
9500         if ( stackGrowsDown() )
 
9501                 Segment::fgStackSegment.setBaseAddress(writer.fOptions.customStackAddr() - writer.fOptions.customStackSize());
 
9503                 Segment::fgStackSegment.setBaseAddress(writer.fOptions.customStackAddr());
 
9507 template <> bool CustomStackAtom<ppc>::stackGrowsDown()    { return true; }
 
9508 template <> bool CustomStackAtom<ppc64>::stackGrowsDown()  { return true; }
 
9509 template <> bool CustomStackAtom<x86>::stackGrowsDown()    { return true; }
 
9510 template <> bool CustomStackAtom<x86_64>::stackGrowsDown() { return true; }
 
9511 template <> bool CustomStackAtom<arm>::stackGrowsDown()    { return true; }
 
9513 template <typename A>
 
9514 void SegmentLoadCommandsAtom<A>::computeSize()
 
9517         std::vector<SegmentInfo*>& segmentInfos = fWriter.fSegmentInfos;
 
9519         for(std::vector<SegmentInfo*>::iterator it = segmentInfos.begin(); it != segmentInfos.end(); ++it) {
 
9520                 SegmentInfo* seg = *it;
 
9521                 if ( seg->fHasLoadCommand ) {
 
9523                         size += sizeof(macho_segment_command<P>);
 
9524                         std::vector<SectionInfo*>& sectionInfos = seg->fSections;
 
9525                         const int sectionCount = sectionInfos.size();
 
9526                         for(int j=0; j < sectionCount; ++j) {
 
9527                                 if ( fWriter.fEmitVirtualSections || ! sectionInfos[j]->fVirtualSection )
 
9528                                         size += sizeof(macho_section<P>);
 
9533         fCommandCount = segCount;
 
9534         if ( fWriter.fPadSegmentInfo != NULL ) {
 
9536                 fSize += sizeof(macho_segment_command<P>);
 
9541 uint64_t LoadCommandAtom<ppc>::alignedSize(uint64_t size)
 
9543         return ((size+3) & (-4));       // 4-byte align all load commands for 32-bit mach-o
 
9547 uint64_t LoadCommandAtom<ppc64>::alignedSize(uint64_t size)
 
9549         return ((size+7) & (-8));       // 8-byte align all load commands for 64-bit mach-o
 
9553 uint64_t LoadCommandAtom<x86>::alignedSize(uint64_t size)
 
9555         return ((size+3) & (-4));       // 4-byte align all load commands for 32-bit mach-o
 
9559 uint64_t LoadCommandAtom<x86_64>::alignedSize(uint64_t size)
 
9561         return ((size+7) & (-8));       // 8-byte align all load commands for 64-bit mach-o
 
9565 uint64_t LoadCommandAtom<arm>::alignedSize(uint64_t size)
 
9567         return ((size+3) & (-4));       // 4-byte align all load commands for 32-bit mach-o
 
9570 template <typename A>
 
9571 void SegmentLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
9573         uint64_t size = this->getSize();
 
9574         const bool oneSegment =( fWriter.fOptions.outputKind() == Options::kObjectFile );
 
9575         bzero(buffer, size);
 
9576         uint8_t* p = buffer;
 
9577         typename std::vector<SegmentInfo*>& segmentInfos = fWriter.fSegmentInfos;
 
9578         for(std::vector<SegmentInfo*>::iterator it = segmentInfos.begin(); it != segmentInfos.end(); ++it) {
 
9579                 SegmentInfo* segInfo = *it;
 
9580                 if ( ! segInfo->fHasLoadCommand )
 
9582                 const int sectionCount = segInfo->fSections.size();
 
9583                 macho_segment_command<P>* cmd = (macho_segment_command<P>*)p;
 
9584                 cmd->set_cmd(macho_segment_command<P>::CMD);
 
9585                 cmd->set_segname(segInfo->fName);
 
9586                 cmd->set_vmaddr(segInfo->fBaseAddress);
 
9587                 cmd->set_vmsize(oneSegment ? 0 : segInfo->fSize);
 
9588                 cmd->set_fileoff(segInfo->fFileOffset);
 
9589                 cmd->set_filesize(oneSegment ? 0 : segInfo->fFileSize);
 
9590                 cmd->set_maxprot(segInfo->fMaxProtection);
 
9591                 cmd->set_initprot(segInfo->fInitProtection);
 
9592                 // add sections array
 
9593                 macho_section<P>* const sections = (macho_section<P>*)&p[sizeof(macho_segment_command<P>)];
 
9594                 unsigned int sectionsEmitted = 0;
 
9595                 for (int j=0; j < sectionCount; ++j) {
 
9596                         SectionInfo* sectInfo = segInfo->fSections[j];
 
9597                         if ( fWriter.fEmitVirtualSections || !sectInfo->fVirtualSection ) {
 
9598                                 macho_section<P>* sect = §ions[sectionsEmitted++];
 
9600                                         // .o file segment does not cover load commands, so recalc at first real section
 
9601                                         if ( sectionsEmitted == 1 ) {
 
9602                                                 cmd->set_vmaddr(sectInfo->getBaseAddress());
 
9603                                                 cmd->set_fileoff(sectInfo->fFileOffset);
 
9605                                         cmd->set_filesize((sectInfo->fFileOffset+sectInfo->fSize)-cmd->fileoff());
 
9606                                         cmd->set_vmsize(sectInfo->getBaseAddress() + sectInfo->fSize);
 
9608                                 sect->set_sectname(sectInfo->fSectionName);
 
9609                                 sect->set_segname(sectInfo->fSegmentName);
 
9610                                 sect->set_addr(sectInfo->getBaseAddress());
 
9611                                 sect->set_size(sectInfo->fSize);
 
9612                                 sect->set_offset(sectInfo->fFileOffset);
 
9613                                 sect->set_align(sectInfo->fAlignment);
 
9614                                 if ( sectInfo->fRelocCount != 0 ) {
 
9615                                         sect->set_reloff(sectInfo->fRelocOffset * sizeof(macho_relocation_info<P>) + fWriter.fSectionRelocationsAtom->getFileOffset());
 
9616                                         sect->set_nreloc(sectInfo->fRelocCount);
 
9618                                 if ( sectInfo->fAllZeroFill ) {
 
9619                                         sect->set_flags(S_ZEROFILL);
 
9620                                         sect->set_offset(0);
 
9622                                 else if ( sectInfo->fAllLazyPointers ) {
 
9623                                         sect->set_flags(S_LAZY_SYMBOL_POINTERS);
 
9624                                         sect->set_reserved1(sectInfo->fIndirectSymbolOffset);
 
9626                                 else if ( sectInfo->fAllLazyDylibPointers ) {
 
9627                                         sect->set_flags(S_LAZY_DYLIB_SYMBOL_POINTERS);
 
9628                                         sect->set_reserved1(sectInfo->fIndirectSymbolOffset);
 
9630                                 else if ( sectInfo->fAllNonLazyPointers ) {
 
9631                                         sect->set_flags(S_NON_LAZY_SYMBOL_POINTERS);
 
9632                                         sect->set_reserved1(sectInfo->fIndirectSymbolOffset);
 
9634                                 else if ( sectInfo->fAllStubs ) {
 
9635                                         sect->set_flags(S_SYMBOL_STUBS | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS);
 
9636                                         sect->set_reserved1(sectInfo->fIndirectSymbolOffset);
 
9637                                         sect->set_reserved2(sectInfo->fSize / sectInfo->fAtoms.size());
 
9638                                         if ( sectInfo->fHasTextLocalRelocs )
 
9639                                                 sect->set_flags(sect->flags() | S_ATTR_LOC_RELOC);
 
9641                                 else if ( sectInfo->fAllSelfModifyingStubs ) {
 
9642                                         sect->set_flags(S_SYMBOL_STUBS | S_ATTR_SELF_MODIFYING_CODE);
 
9643                                         sect->set_reserved1(sectInfo->fIndirectSymbolOffset);
 
9644                                         sect->set_reserved2(sectInfo->fSize / sectInfo->fAtoms.size());
 
9646                                 else if ( sectInfo->fAllStubHelpers ) {
 
9647                                         sect->set_flags(S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS);
 
9648                                         if ( sectInfo->fHasTextLocalRelocs )
 
9649                                                 sect->set_flags(sect->flags() | S_ATTR_LOC_RELOC);
 
9651                                 else if ( sectInfo->fAtoms.at(0)->getContentType() == ObjectFile::Atom::kCStringType ) {
 
9652                                         sect->set_flags(S_CSTRING_LITERALS);
 
9654                                 else if ( sectInfo->fAtoms.at(0)->getContentType() == ObjectFile::Atom::kCFIType ) {
 
9655                                         sect->set_flags(S_COALESCED | S_ATTR_NO_TOC | S_ATTR_STRIP_STATIC_SYMS);
 
9657                                 else if ( (strcmp(sectInfo->fSectionName, "__mod_init_func") == 0) && (strcmp(sectInfo->fSegmentName, "__DATA") == 0) ) {
 
9658                                         sect->set_flags(S_MOD_INIT_FUNC_POINTERS);
 
9660                                 else if ( (strcmp(sectInfo->fSectionName, "__mod_term_func") == 0) && (strcmp(sectInfo->fSegmentName, "__DATA") == 0) ) {
 
9661                                         sect->set_flags(S_MOD_TERM_FUNC_POINTERS);
 
9663                                 else if ( (strcmp(sectInfo->fSectionName, "__textcoal_nt") == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
9664                                         sect->set_flags(S_COALESCED);
 
9666                                 else if ( (strcmp(sectInfo->fSectionName, "__const_coal") == 0) && (strcmp(sectInfo->fSegmentName, "__DATA") == 0) ) {
 
9667                                         sect->set_flags(S_COALESCED);
 
9669                                 else if ( (strcmp(sectInfo->fSectionName, "__interpose") == 0) && (strcmp(sectInfo->fSegmentName, "__DATA") == 0) ) {
 
9670                                         sect->set_flags(S_INTERPOSING);
 
9672                                 else if ( (strcmp(sectInfo->fSectionName, "__literal4") == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
9673                                         sect->set_flags(S_4BYTE_LITERALS);
 
9675                                 else if ( (strcmp(sectInfo->fSectionName, "__literal8") == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
9676                                         sect->set_flags(S_8BYTE_LITERALS);
 
9678                                 else if ( (strcmp(sectInfo->fSectionName, "__literal16") == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
9679                                         sect->set_flags(S_16BYTE_LITERALS);
 
9681                                 else if ( (strcmp(sectInfo->fSectionName, "__message_refs") == 0) && (strcmp(sectInfo->fSegmentName, "__OBJC") == 0) ) {
 
9682                                         sect->set_flags(S_LITERAL_POINTERS);
 
9684                                 else if ( (strcmp(sectInfo->fSectionName, "__objc_selrefs") == 0) && (strcmp(sectInfo->fSegmentName, "__DATA") == 0) ) {
 
9685                                         sect->set_flags(S_LITERAL_POINTERS);
 
9687                                 else if ( (strcmp(sectInfo->fSectionName, "__cls_refs") == 0) && (strcmp(sectInfo->fSegmentName, "__OBJC") == 0) ) {
 
9688                                         sect->set_flags(S_LITERAL_POINTERS);
 
9690                                 else if ( (strncmp(sectInfo->fSectionName, "__dof_", 6) == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
9691                                         sect->set_flags(S_DTRACE_DOF);
 
9693                                 else if ( (strncmp(sectInfo->fSectionName, "__dof_", 6) == 0) && (strcmp(sectInfo->fSegmentName, "__DATA") == 0) ) {
 
9694                                         sect->set_flags(S_DTRACE_DOF);
 
9696                                 else if ( (strncmp(sectInfo->fSectionName, "__text", 6) == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
9697                                         sect->set_flags(S_REGULAR | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS);
 
9698                                         if ( sectInfo->fHasTextLocalRelocs )
 
9699                                                 sect->set_flags(sect->flags() | S_ATTR_LOC_RELOC);
 
9700                                         if ( sectInfo->fHasTextExternalRelocs )
 
9701                                                 sect->set_flags(sect->flags() | S_ATTR_EXT_RELOC);
 
9703                                 //fprintf(stderr, "section %s flags=0x%08X\n", sectInfo->fSectionName, sect->flags());
 
9706                 p = &p[sizeof(macho_segment_command<P>) + sectionsEmitted*sizeof(macho_section<P>)];
 
9707                 cmd->set_cmdsize(sizeof(macho_segment_command<P>) + sectionsEmitted*sizeof(macho_section<P>));
 
9708                 cmd->set_nsects(sectionsEmitted);
 
9713 template <typename A>
 
9714 SymbolTableLoadCommandsAtom<A>::SymbolTableLoadCommandsAtom(Writer<A>& writer)
 
9715  : LoadCommandAtom<A>(writer), fNeedsDynamicSymbolTable(false)
 
9717         bzero(&fSymbolTable, sizeof(macho_symtab_command<P>));
 
9718         bzero(&fDynamicSymbolTable, sizeof(macho_dysymtab_command<P>));
 
9719         switch ( fWriter.fOptions.outputKind() ) {
 
9720                 case Options::kDynamicExecutable:
 
9721                 case Options::kDynamicLibrary:
 
9722                 case Options::kDynamicBundle:
 
9723                 case Options::kDyld:
 
9724                 case Options::kKextBundle:
 
9725                         fNeedsDynamicSymbolTable = true;
 
9727                 case Options::kObjectFile:
 
9728                 case Options::kStaticExecutable:
 
9729                         fNeedsDynamicSymbolTable = false;
 
9730                 case Options::kPreload:
 
9731                         fNeedsDynamicSymbolTable = fWriter.fOptions.positionIndependentExecutable();
 
9734         writer.fSymbolTableCommands = this;
 
9739 template <typename A>
 
9740 void SymbolTableLoadCommandsAtom<A>::needDynamicTable() 
 
9742         fNeedsDynamicSymbolTable = true;
 
9746 template <typename A>
 
9747 uint64_t SymbolTableLoadCommandsAtom<A>::getSize() const
 
9749         if ( fNeedsDynamicSymbolTable )
 
9750                 return this->alignedSize(sizeof(macho_symtab_command<P>) + sizeof(macho_dysymtab_command<P>));
 
9752                 return this->alignedSize(sizeof(macho_symtab_command<P>));
 
9755 template <typename A>
 
9756 void SymbolTableLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
9758         // build LC_SYMTAB command
 
9759         macho_symtab_command<P>*   symbolTableCmd = (macho_symtab_command<P>*)buffer;
 
9760         bzero(symbolTableCmd, sizeof(macho_symtab_command<P>));
 
9761         symbolTableCmd->set_cmd(LC_SYMTAB);
 
9762         symbolTableCmd->set_cmdsize(sizeof(macho_symtab_command<P>));
 
9763         symbolTableCmd->set_nsyms(fWriter.fSymbolTableCount);
 
9764         symbolTableCmd->set_symoff(fWriter.fSymbolTableCount == 0 ? 0 : fWriter.fSymbolTableAtom->getFileOffset());
 
9765         symbolTableCmd->set_stroff(fWriter.fStringsAtom->getSize() == 0 ? 0 : fWriter.fStringsAtom->getFileOffset());
 
9766         symbolTableCmd->set_strsize(fWriter.fStringsAtom->getSize());
 
9768         // build LC_DYSYMTAB command
 
9769         if ( fNeedsDynamicSymbolTable ) {
 
9770                 macho_dysymtab_command<P>* dynamicSymbolTableCmd = (macho_dysymtab_command<P>*)&buffer[sizeof(macho_symtab_command<P>)];
 
9771                 bzero(dynamicSymbolTableCmd, sizeof(macho_dysymtab_command<P>));
 
9772                 dynamicSymbolTableCmd->set_cmd(LC_DYSYMTAB);
 
9773                 dynamicSymbolTableCmd->set_cmdsize(sizeof(macho_dysymtab_command<P>));
 
9774                 dynamicSymbolTableCmd->set_ilocalsym(fWriter.fSymbolTableStabsStartIndex);
 
9775                 dynamicSymbolTableCmd->set_nlocalsym(fWriter.fSymbolTableStabsCount + fWriter.fSymbolTableLocalCount);
 
9776                 dynamicSymbolTableCmd->set_iextdefsym(fWriter.fSymbolTableExportStartIndex);
 
9777                 dynamicSymbolTableCmd->set_nextdefsym(fWriter.fSymbolTableExportCount);
 
9778                 dynamicSymbolTableCmd->set_iundefsym(fWriter.fSymbolTableImportStartIndex);
 
9779                 dynamicSymbolTableCmd->set_nundefsym(fWriter.fSymbolTableImportCount);
 
9780                 if ( fWriter.fModuleInfoAtom != NULL ) {
 
9781                         dynamicSymbolTableCmd->set_tocoff(fWriter.fModuleInfoAtom->getTableOfContentsFileOffset());
 
9782                         dynamicSymbolTableCmd->set_ntoc(fWriter.fSymbolTableExportCount);
 
9783                         dynamicSymbolTableCmd->set_modtaboff(fWriter.fModuleInfoAtom->getModuleTableFileOffset());
 
9784                         dynamicSymbolTableCmd->set_nmodtab(1);
 
9785                         dynamicSymbolTableCmd->set_extrefsymoff(fWriter.fModuleInfoAtom->getReferencesFileOffset());
 
9786                         dynamicSymbolTableCmd->set_nextrefsyms(fWriter.fModuleInfoAtom->getReferencesCount());
 
9788                 dynamicSymbolTableCmd->set_indirectsymoff((fWriter.fIndirectTableAtom == NULL) ? 0 : fWriter.fIndirectTableAtom->getFileOffset());
 
9789                 dynamicSymbolTableCmd->set_nindirectsyms((fWriter.fIndirectTableAtom == NULL) ? 0 : fWriter.fIndirectTableAtom->fTable.size());
 
9790                 if ( fWriter.fOptions.outputKind() != Options::kObjectFile ) {
 
9791                         if ( fWriter.fExternalRelocationsAtom != 0 ) {
 
9792                                 dynamicSymbolTableCmd->set_extreloff((fWriter.fExternalRelocs.size()==0) ? 0 : fWriter.fExternalRelocationsAtom->getFileOffset());
 
9793                                 dynamicSymbolTableCmd->set_nextrel(fWriter.fExternalRelocs.size());
 
9795                         if ( fWriter.fLocalRelocationsAtom != 0 ) {
 
9796                                 dynamicSymbolTableCmd->set_locreloff((fWriter.fInternalRelocs.size()==0) ? 0 : fWriter.fLocalRelocationsAtom->getFileOffset());
 
9797                                 dynamicSymbolTableCmd->set_nlocrel(fWriter.fInternalRelocs.size());
 
9804 template <typename A>
 
9805 unsigned int SymbolTableLoadCommandsAtom<A>::commandCount()
 
9807         return fNeedsDynamicSymbolTable ? 2 : 1;
 
9810 template <typename A>
 
9811 uint64_t DyldLoadCommandsAtom<A>::getSize() const
 
9813         return this->alignedSize(sizeof(macho_dylinker_command<P>) + strlen("/usr/lib/dyld") + 1);
 
9816 template <typename A>
 
9817 void DyldLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
9819         uint64_t size = this->getSize();
 
9820         bzero(buffer, size);
 
9821         macho_dylinker_command<P>* cmd = (macho_dylinker_command<P>*)buffer;
 
9822         if ( fWriter.fOptions.outputKind() == Options::kDyld )
 
9823                 cmd->set_cmd(LC_ID_DYLINKER);
 
9825                 cmd->set_cmd(LC_LOAD_DYLINKER);
 
9826         cmd->set_cmdsize(this->getSize());
 
9827         cmd->set_name_offset();
 
9828         strcpy((char*)&buffer[sizeof(macho_dylinker_command<P>)], "/usr/lib/dyld");
 
9831 template <typename A>
 
9832 uint64_t AllowableClientLoadCommandsAtom<A>::getSize() const
 
9834         return this->alignedSize(sizeof(macho_sub_client_command<P>) + strlen(this->clientString) + 1);
 
9837 template <typename A>
 
9838 void AllowableClientLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
9840         uint64_t size = this->getSize();
 
9842         bzero(buffer, size);
 
9843         macho_sub_client_command<P>* cmd = (macho_sub_client_command<P>*)buffer;
 
9844         cmd->set_cmd(LC_SUB_CLIENT);
 
9845         cmd->set_cmdsize(size);
 
9846         cmd->set_client_offset();
 
9847         strcpy((char*)&buffer[sizeof(macho_sub_client_command<P>)], this->clientString);
 
9851 template <typename A>
 
9852 uint64_t DylibLoadCommandsAtom<A>::getSize() const
 
9854         if ( fOptimizedAway ) {
 
9858                 const char* path = fInfo.reader->getInstallPath();
 
9859                 return this->alignedSize(sizeof(macho_dylib_command<P>) + strlen(path) + 1);
 
9863 template <typename A>
 
9864 void DylibLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
9866         if ( fOptimizedAway ) 
 
9868         uint64_t size = this->getSize();
 
9869         bzero(buffer, size);
 
9870         const char* path = fInfo.reader->getInstallPath();
 
9871         macho_dylib_command<P>* cmd = (macho_dylib_command<P>*)buffer;
 
9872         // <rdar://problem/5529626> If only weak_import symbols are used, linker should use LD_LOAD_WEAK_DYLIB
 
9873         bool autoWeakLoadDylib = ( (fWriter.fDylibReadersWithWeakImports.count(fInfo.reader) > 0) 
 
9874                                                         && (fWriter.fDylibReadersWithNonWeakImports.count(fInfo.reader) == 0) );
 
9875         if ( fInfo.options.fLazyLoad )
 
9876                 cmd->set_cmd(LC_LAZY_LOAD_DYLIB);
 
9877         else if ( fInfo.options.fWeakImport || autoWeakLoadDylib )
 
9878                 cmd->set_cmd(LC_LOAD_WEAK_DYLIB);
 
9879         else if ( fInfo.options.fReExport && fWriter.fOptions.useSimplifiedDylibReExports() )
 
9880                 cmd->set_cmd(LC_REEXPORT_DYLIB);
 
9882                 cmd->set_cmd(LC_LOAD_DYLIB);
 
9883         cmd->set_cmdsize(this->getSize());
 
9884         cmd->set_timestamp(2);  // needs to be some constant value that is different than DylibIDLoadCommandsAtom uses
 
9885         cmd->set_current_version(fInfo.reader->getCurrentVersion());
 
9886         cmd->set_compatibility_version(fInfo.reader->getCompatibilityVersion());
 
9887         cmd->set_name_offset();
 
9888         strcpy((char*)&buffer[sizeof(macho_dylib_command<P>)], path);
 
9893 template <typename A>
 
9894 uint64_t DylibIDLoadCommandsAtom<A>::getSize() const
 
9896         return this->alignedSize(sizeof(macho_dylib_command<P>) + strlen(fWriter.fOptions.installPath()) + 1);
 
9899 template <typename A>
 
9900 void DylibIDLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
9902         uint64_t size = this->getSize();
 
9903         bzero(buffer, size);
 
9904         macho_dylib_command<P>* cmd = (macho_dylib_command<P>*)buffer;
 
9905         cmd->set_cmd(LC_ID_DYLIB);
 
9906         cmd->set_cmdsize(this->getSize());
 
9907         cmd->set_name_offset();
 
9908         cmd->set_timestamp(1);  // needs to be some constant value that is different than DylibLoadCommandsAtom uses
 
9909         cmd->set_current_version(fWriter.fOptions.currentVersion());
 
9910         cmd->set_compatibility_version(fWriter.fOptions.compatibilityVersion());
 
9911         strcpy((char*)&buffer[sizeof(macho_dylib_command<P>)], fWriter.fOptions.installPath());
 
9915 template <typename A>
 
9916 void RoutinesLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
9918         uint64_t initAddr = fWriter.getAtomLoadAddress(fWriter.fEntryPoint);
 
9919         if (fWriter.fEntryPoint->isThumb())
 
9921         bzero(buffer, sizeof(macho_routines_command<P>));
 
9922         macho_routines_command<P>* cmd = (macho_routines_command<P>*)buffer;
 
9923         cmd->set_cmd(macho_routines_command<P>::CMD);
 
9924         cmd->set_cmdsize(this->getSize());
 
9925         cmd->set_init_address(initAddr);
 
9929 template <typename A>
 
9930 uint64_t SubUmbrellaLoadCommandsAtom<A>::getSize() const
 
9932         return this->alignedSize(sizeof(macho_sub_umbrella_command<P>) + strlen(fName) + 1);
 
9935 template <typename A>
 
9936 void SubUmbrellaLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
9938         uint64_t size = this->getSize();
 
9939         bzero(buffer, size);
 
9940         macho_sub_umbrella_command<P>* cmd = (macho_sub_umbrella_command<P>*)buffer;
 
9941         cmd->set_cmd(LC_SUB_UMBRELLA);
 
9942         cmd->set_cmdsize(this->getSize());
 
9943         cmd->set_sub_umbrella_offset();
 
9944         strcpy((char*)&buffer[sizeof(macho_sub_umbrella_command<P>)], fName);
 
9947 template <typename A>
 
9948 void UUIDLoadCommandAtom<A>::generate() 
 
9950         switch ( fWriter.fOptions.getUUIDMode() ) {
 
9951                 case Options::kUUIDNone: 
 
9954                 case Options::kUUIDRandom:
 
9955                         ::uuid_generate_random(fUUID);
 
9958                 case Options::kUUIDContent: 
 
9965 template <typename A>
 
9966 void UUIDLoadCommandAtom<A>::setContent(const uint8_t uuid[16]) 
 
9968         memcpy(fUUID, uuid, 16);
 
9971 template <typename A>
 
9972 void UUIDLoadCommandAtom<A>::copyRawContent(uint8_t buffer[]) const
 
9975                 uint64_t size = this->getSize();
 
9976                 bzero(buffer, size);
 
9977                 macho_uuid_command<P>* cmd = (macho_uuid_command<P>*)buffer;
 
9978                 cmd->set_cmd(LC_UUID);
 
9979                 cmd->set_cmdsize(this->getSize());
 
9980                 cmd->set_uuid((uint8_t*)fUUID);
 
9985 template <typename A>
 
9986 uint64_t SubLibraryLoadCommandsAtom<A>::getSize() const
 
9988         return this->alignedSize(sizeof(macho_sub_library_command<P>) + fNameLength + 1);
 
9991 template <typename A>
 
9992 void SubLibraryLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
9994         uint64_t size = this->getSize();
 
9995         bzero(buffer, size);
 
9996         macho_sub_library_command<P>* cmd = (macho_sub_library_command<P>*)buffer;
 
9997         cmd->set_cmd(LC_SUB_LIBRARY);
 
9998         cmd->set_cmdsize(this->getSize());
 
9999         cmd->set_sub_library_offset();
 
10000         strncpy((char*)&buffer[sizeof(macho_sub_library_command<P>)], fNameStart, fNameLength);
 
10001         buffer[sizeof(macho_sub_library_command<P>)+fNameLength] = '\0';
 
10004 template <typename A>
 
10005 uint64_t UmbrellaLoadCommandsAtom<A>::getSize() const
 
10007         return this->alignedSize(sizeof(macho_sub_framework_command<P>) + strlen(fName) + 1);
 
10010 template <typename A>
 
10011 void UmbrellaLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
10013         uint64_t size = this->getSize();
 
10014         bzero(buffer, size);
 
10015         macho_sub_framework_command<P>* cmd = (macho_sub_framework_command<P>*)buffer;
 
10016         cmd->set_cmd(LC_SUB_FRAMEWORK);
 
10017         cmd->set_cmdsize(this->getSize());
 
10018         cmd->set_umbrella_offset();
 
10019         strcpy((char*)&buffer[sizeof(macho_sub_framework_command<P>)], fName);
 
10023 uint64_t ThreadsLoadCommandsAtom<ppc>::getSize() const
 
10025         return this->alignedSize(16 + 40*4);    // base size + PPC_THREAD_STATE_COUNT * 4
 
10029 uint64_t ThreadsLoadCommandsAtom<ppc64>::getSize() const
 
10031         return this->alignedSize(16 + 76*4);    // base size + PPC_THREAD_STATE64_COUNT * 4
 
10035 uint64_t ThreadsLoadCommandsAtom<x86>::getSize() const
 
10037         return this->alignedSize(16 + 16*4);    // base size + i386_THREAD_STATE_COUNT * 4
 
10041 uint64_t ThreadsLoadCommandsAtom<x86_64>::getSize() const
 
10043         return this->alignedSize(16 + x86_THREAD_STATE64_COUNT * 4); 
 
10046 // We should be picking it up from a header
 
10048 uint64_t ThreadsLoadCommandsAtom<arm>::getSize() const
 
10050         return this->alignedSize(16 + 17 * 4); // base size + ARM_THREAD_STATE_COUNT * 4
 
10054 void ThreadsLoadCommandsAtom<ppc>::copyRawContent(uint8_t buffer[]) const
 
10056         uint64_t size = this->getSize();
 
10057         uint64_t start = fWriter.getAtomLoadAddress(fWriter.fEntryPoint);
 
10058         bzero(buffer, size);
 
10059         macho_thread_command<ppc::P>* cmd = (macho_thread_command<ppc::P>*)buffer;
 
10060         cmd->set_cmd(LC_UNIXTHREAD);
 
10061         cmd->set_cmdsize(size);
 
10062         cmd->set_flavor(1);                             // PPC_THREAD_STATE
 
10063         cmd->set_count(40);                             // PPC_THREAD_STATE_COUNT;
 
10064         cmd->set_thread_register(0, start);
 
10065         if ( fWriter.fOptions.hasCustomStack() )
 
10066                 cmd->set_thread_register(3, fWriter.fOptions.customStackAddr());        // r1
 
10071 void ThreadsLoadCommandsAtom<ppc64>::copyRawContent(uint8_t buffer[]) const
 
10073         uint64_t size = this->getSize();
 
10074         uint64_t start = fWriter.getAtomLoadAddress(fWriter.fEntryPoint);
 
10075         bzero(buffer, size);
 
10076         macho_thread_command<ppc64::P>* cmd = (macho_thread_command<ppc64::P>*)buffer;
 
10077         cmd->set_cmd(LC_UNIXTHREAD);
 
10078         cmd->set_cmdsize(size);
 
10079         cmd->set_flavor(5);                             // PPC_THREAD_STATE64
 
10080         cmd->set_count(76);                             // PPC_THREAD_STATE64_COUNT;
 
10081         cmd->set_thread_register(0, start);
 
10082         if ( fWriter.fOptions.hasCustomStack() )
 
10083                 cmd->set_thread_register(3, fWriter.fOptions.customStackAddr());        // r1
 
10087 void ThreadsLoadCommandsAtom<x86>::copyRawContent(uint8_t buffer[]) const
 
10089         uint64_t size = this->getSize();
 
10090         uint64_t start = fWriter.getAtomLoadAddress(fWriter.fEntryPoint);
 
10091         bzero(buffer, size);
 
10092         macho_thread_command<x86::P>* cmd = (macho_thread_command<x86::P>*)buffer;
 
10093         cmd->set_cmd(LC_UNIXTHREAD);
 
10094         cmd->set_cmdsize(size);
 
10095         cmd->set_flavor(1);                             // i386_THREAD_STATE
 
10096         cmd->set_count(16);                             // i386_THREAD_STATE_COUNT;
 
10097         cmd->set_thread_register(10, start);
 
10098         if ( fWriter.fOptions.hasCustomStack() )
 
10099                 cmd->set_thread_register(7, fWriter.fOptions.customStackAddr());        // esp
 
10103 void ThreadsLoadCommandsAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
 
10105         uint64_t size = this->getSize();
 
10106         uint64_t start = fWriter.getAtomLoadAddress(fWriter.fEntryPoint);
 
10107         bzero(buffer, size);
 
10108         macho_thread_command<x86_64::P>* cmd = (macho_thread_command<x86_64::P>*)buffer;
 
10109         cmd->set_cmd(LC_UNIXTHREAD);
 
10110         cmd->set_cmdsize(size);
 
10111         cmd->set_flavor(x86_THREAD_STATE64);                    
 
10112         cmd->set_count(x86_THREAD_STATE64_COUNT);       
 
10113         cmd->set_thread_register(16, start);            // rip 
 
10114         if ( fWriter.fOptions.hasCustomStack() )
 
10115                 cmd->set_thread_register(7, fWriter.fOptions.customStackAddr());        // uesp
 
10119 void ThreadsLoadCommandsAtom<arm>::copyRawContent(uint8_t buffer[]) const
 
10121         uint64_t size = this->getSize();
 
10122         uint64_t start = fWriter.getAtomLoadAddress(fWriter.fEntryPoint);
 
10123         if ( fWriter.fEntryPoint->isThumb() )
 
10125         bzero(buffer, size);
 
10126         macho_thread_command<arm::P>* cmd = (macho_thread_command<arm::P>*)buffer;
 
10127         cmd->set_cmd(LC_UNIXTHREAD);
 
10128         cmd->set_cmdsize(size);
 
10129         cmd->set_flavor(1);                     
 
10130         cmd->set_count(17);     
 
10131         cmd->set_thread_register(15, start);            // pc
 
10132         if ( fWriter.fOptions.hasCustomStack() )
 
10133                 cmd->set_thread_register(13, fWriter.fOptions.customStackAddr());       // FIXME: sp?
 
10136 template <typename A>
 
10137 uint64_t RPathLoadCommandsAtom<A>::getSize() const
 
10139         return this->alignedSize(sizeof(macho_rpath_command<P>) + strlen(fPath) + 1);
 
10142 template <typename A>
 
10143 void RPathLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
10145         uint64_t size = this->getSize();
 
10146         bzero(buffer, size);
 
10147         macho_rpath_command<P>* cmd = (macho_rpath_command<P>*)buffer;
 
10148         cmd->set_cmd(LC_RPATH);
 
10149         cmd->set_cmdsize(this->getSize());
 
10150         cmd->set_path_offset();
 
10151         strcpy((char*)&buffer[sizeof(macho_rpath_command<P>)], fPath);
 
10156 template <typename A>
 
10157 void EncryptionLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
10159         uint64_t size = this->getSize();
 
10160         bzero(buffer, size);
 
10161         macho_encryption_info_command<P>* cmd = (macho_encryption_info_command<P>*)buffer;
 
10162         cmd->set_cmd(LC_ENCRYPTION_INFO);
 
10163         cmd->set_cmdsize(this->getSize());
 
10164         cmd->set_cryptoff(fStartOffset);
 
10165         cmd->set_cryptsize(fEndOffset-fStartOffset);
 
10166         cmd->set_cryptid(0);
 
10171 template <typename A>
 
10172 void LoadCommandsPaddingAtom<A>::copyRawContent(uint8_t buffer[]) const
 
10174         bzero(buffer, fSize);
 
10177 template <typename A>
 
10178 void LoadCommandsPaddingAtom<A>::setSize(uint64_t newSize) 
 
10181         // this resizing by-passes the way fLargestAtomSize is set, so re-check here
 
10182         if ( fWriter.fLargestAtomSize < newSize )
 
10183                 fWriter.fLargestAtomSize = newSize;
 
10186 template <typename A>
 
10187 void UnwindInfoAtom<A>::addUnwindInfo(ObjectFile::Atom* func, uint32_t offset, uint32_t encoding, 
 
10188                                                                                 ObjectFile::Reference* fdeRef, ObjectFile::Reference* lsdaRef,
 
10189                                                                                 ObjectFile::Atom* personalityPointer) 
 
10193         if ( fdeRef != NULL )  
 
10194                 info.fde = &fdeRef->getTarget();
 
10197         if ( lsdaRef != NULL )  {
 
10198                 info.lsda = &lsdaRef->getTarget();
 
10199                 info.lsdaOffset = lsdaRef->getTargetOffset();
 
10203                 info.lsdaOffset = 0;
 
10205         info.personalityPointer = personalityPointer;
 
10206         info.encoding = encoding;
 
10207         fInfos.push_back(info);
 
10208         //fprintf(stderr, "addUnwindInfo() encoding=0x%08X, lsda=%p, lsdaOffset=%d, person=%p, func=%s\n", 
 
10209         //                              encoding, info.lsda, info.lsdaOffset, personalityPointer, func->getDisplayName());
 
10213 bool UnwindInfoAtom<x86>::encodingMeansUseDwarf(compact_unwind_encoding_t encoding)
 
10215         return ( (encoding & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF);
 
10219 bool UnwindInfoAtom<x86_64>::encodingMeansUseDwarf(compact_unwind_encoding_t encoding)
 
10221         return ( (encoding & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF);
 
10224 template <typename A>
 
10225 bool UnwindInfoAtom<A>::encodingMeansUseDwarf(compact_unwind_encoding_t encoding)
 
10231 template <typename A>
 
10232 void UnwindInfoAtom<A>::compressDuplicates(std::vector<Info>& uniqueInfos)
 
10234         // build new list removing entries where next function has same encoding 
 
10235         uniqueInfos.reserve(fInfos.size());
 
10239         last.lsdaOffset = 0;
 
10240         last.personalityPointer = NULL;
 
10241         last.encoding = 0xFFFFFFFF;
 
10242         for(typename std::vector<Info>::iterator it=fInfos.begin(); it != fInfos.end(); ++it) {
 
10243                 Info& newInfo = *it;
 
10244                 bool newNeedsDwarf = encodingMeansUseDwarf(newInfo.encoding);
 
10245                 // remove infos which have same encoding and personalityPointer as last one
 
10246                 if ( newNeedsDwarf || (newInfo.encoding != last.encoding) || (newInfo.personalityPointer != last.personalityPointer) 
 
10247                                                 || (newInfo.lsda != NULL) || (last.lsda != NULL) ) {
 
10248                         uniqueInfos.push_back(newInfo);
 
10252         //fprintf(stderr, "compressDuplicates() fInfos.size()=%lu, uniqueInfos.size()=%lu\n", fInfos.size(), uniqueInfos.size());
 
10255 template <typename A>
 
10256 void UnwindInfoAtom<A>::findCommonEncoding(const std::vector<Info>& uniqueInfos, std::map<uint32_t, unsigned int>& commonEncodings)
 
10258         // scan infos to get frequency counts for each encoding
 
10259         std::map<uint32_t, unsigned int> encodingsUsed;
 
10260         unsigned int mostCommonEncodingUsageCount = 0;
 
10261         for(typename std::vector<Info>::const_iterator it=uniqueInfos.begin(); it != uniqueInfos.end(); ++it) {
 
10262                 // never put dwarf into common table
 
10263                 if ( encodingMeansUseDwarf(it->encoding) )
 
10265                 std::map<uint32_t, unsigned int>::iterator pos = encodingsUsed.find(it->encoding);
 
10266                 if ( pos == encodingsUsed.end() ) {
 
10267                         encodingsUsed[it->encoding] = 1;
 
10270                         encodingsUsed[it->encoding] += 1;
 
10271                         if ( mostCommonEncodingUsageCount < encodingsUsed[it->encoding] )
 
10272                                 mostCommonEncodingUsageCount = encodingsUsed[it->encoding];
 
10275         // put the most common encodings into the common table, but at most 127 of them
 
10276         for(unsigned int usages=mostCommonEncodingUsageCount; usages > 1; --usages) {
 
10277                 for (std::map<uint32_t, unsigned int>::iterator euit=encodingsUsed.begin(); euit != encodingsUsed.end(); ++euit) {
 
10278                         if ( euit->second == usages ) {
 
10279                                 unsigned int size = commonEncodings.size();
 
10280                                 if ( size < 127 ) {
 
10281                                         commonEncodings[euit->first] = size;
 
10288 template <typename A>
 
10289 void UnwindInfoAtom<A>::makeLsdaIndex(const std::vector<Info>& uniqueInfos, std::map<ObjectFile::Atom*, uint32_t>& lsdaIndexOffsetMap)
 
10291         for(typename std::vector<Info>::const_iterator it=uniqueInfos.begin(); it != uniqueInfos.end(); ++it) {
 
10292                 lsdaIndexOffsetMap[it->func] = fLSDAIndex.size() * sizeof(macho_unwind_info_section_header_lsda_index_entry<P>);
 
10293                 if ( it->lsda != NULL ) {
 
10295                         entry.func = it->func;
 
10296                         entry.lsda = it->lsda;
 
10297                         entry.lsdaOffset = it->lsdaOffset;
 
10298                         fLSDAIndex.push_back(entry);
 
10303 template <typename A>
 
10304 void UnwindInfoAtom<A>::makePersonalityIndex(std::vector<Info>& uniqueInfos)
 
10306         for(typename std::vector<Info>::iterator it=uniqueInfos.begin(); it != uniqueInfos.end(); ++it) {
 
10307                 if ( it->personalityPointer != NULL ) {
 
10308                         std::map<ObjectFile::Atom*, uint32_t>::iterator pos = fPersonalityIndexMap.find(it->personalityPointer);
 
10309                         if ( pos == fPersonalityIndexMap.end() ) {
 
10310                                 const uint32_t nextIndex = fPersonalityIndexMap.size() + 1;
 
10311                                 fPersonalityIndexMap[it->personalityPointer] = nextIndex;
 
10313                         uint32_t personalityIndex = fPersonalityIndexMap[it->personalityPointer];
 
10314                         it->encoding |= (personalityIndex << (__builtin_ctz(UNWIND_PERSONALITY_MASK)) );
 
10319 template <typename A>
 
10320 unsigned int UnwindInfoAtom<A>::makeRegularSecondLevelPage(const std::vector<Info>& uniqueInfos, uint32_t pageSize,  
 
10321                                                                                                                         unsigned int endIndex, uint8_t*& pageEnd)
 
10323         const unsigned int maxEntriesPerPage = (pageSize - sizeof(unwind_info_regular_second_level_page_header))/sizeof(unwind_info_regular_second_level_entry);
 
10324         const unsigned int entriesToAdd = ((endIndex > maxEntriesPerPage) ? maxEntriesPerPage : endIndex);
 
10325         uint8_t* pageStart = pageEnd 
 
10326                                                 - entriesToAdd*sizeof(unwind_info_regular_second_level_entry) 
 
10327                                                 - sizeof(unwind_info_regular_second_level_page_header);
 
10328         macho_unwind_info_regular_second_level_page_header<P>* page = (macho_unwind_info_regular_second_level_page_header<P>*)pageStart;
 
10329         page->set_kind(UNWIND_SECOND_LEVEL_REGULAR);
 
10330         page->set_entryPageOffset(sizeof(macho_unwind_info_regular_second_level_page_header<P>));
 
10331         page->set_entryCount(entriesToAdd);
 
10332         macho_unwind_info_regular_second_level_entry<P>* entryTable = (macho_unwind_info_regular_second_level_entry<P>*)(pageStart + page->entryPageOffset());
 
10333         for (unsigned int i=0; i < entriesToAdd; ++i) {
 
10334                 const Info& info = uniqueInfos[endIndex-entriesToAdd+i];
 
10335                 entryTable[i].set_functionOffset(0);
 
10336                 entryTable[i].set_encoding(info.encoding);
 
10338                 fixup.contentPointer = (uint8_t*)(&entryTable[i]);
 
10339                 fixup.func = info.func;
 
10340                 fixup.fde = ( encodingMeansUseDwarf(info.encoding) ? info.fde : NULL );
 
10341                 fRegFixUps.push_back(fixup);
 
10343         //fprintf(stderr, "regular page with %u entries\n", entriesToAdd);
 
10344         pageEnd = pageStart;
 
10345         return endIndex - entriesToAdd;
 
10349 template <typename A>
 
10350 unsigned int UnwindInfoAtom<A>::makeCompressedSecondLevelPage(const std::vector<Info>& uniqueInfos,   
 
10351                                                                                                                         const std::map<uint32_t,unsigned int> commonEncodings,  
 
10352                                                                                                                         uint32_t pageSize, unsigned int endIndex, uint8_t*& pageEnd)
 
10354         const bool log = false;
 
10355         if (log) fprintf(stderr, "makeCompressedSecondLevelPage(pageSize=%u, endIndex=%u)\n", pageSize, endIndex);
 
10356         // first pass calculates how many compressed entries we could fit in this sized page
 
10357         // keep adding entries to page until:
 
10358         //  1) encoding table plus entry table plus header exceed page size
 
10359         //  2) the file offset delta from the first to last function > 24 bits
 
10360         //  3) custom encoding index reachs 255
 
10361         //  4) run out of uniqueInfos to encode
 
10362         std::map<uint32_t, unsigned int> pageSpecificEncodings;
 
10363         uint32_t space4 =  (pageSize - sizeof(unwind_info_compressed_second_level_page_header))/sizeof(uint32_t);
 
10364         std::vector<uint8_t> encodingIndexes;
 
10365         int index = endIndex-1;
 
10366         int entryCount = 0;
 
10367         uint64_t lastEntryAddress = uniqueInfos[index].func->getAddress();
 
10369         while ( canDo && (index >= 0) ) {
 
10370                 const Info& info = uniqueInfos[index--];
 
10371                 // compute encoding index
 
10372                 unsigned int encodingIndex;
 
10373                 std::map<uint32_t, unsigned int>::const_iterator pos = commonEncodings.find(info.encoding);
 
10374                 if ( pos != commonEncodings.end() ) {
 
10375                         encodingIndex = pos->second;
 
10378                         // no commmon entry, so add one on this page
 
10379                         uint32_t encoding = info.encoding;
 
10380                         if ( encodingMeansUseDwarf(encoding) ) {
 
10381                                 // make unique pseudo encoding so this dwarf will gets is own encoding entry slot
 
10382                                 encoding += (index+1);
 
10384                         std::map<uint32_t, unsigned int>::iterator ppos = pageSpecificEncodings.find(encoding);
 
10385                         if ( ppos != pageSpecificEncodings.end() ) {
 
10386                                 encodingIndex = pos->second;
 
10389                                 encodingIndex = commonEncodings.size() + pageSpecificEncodings.size();
 
10390                                 if ( encodingIndex <= 255 ) {
 
10391                                         pageSpecificEncodings[encoding] = encodingIndex;
 
10394                                         canDo = false; // case 3)
 
10395                                         if (log) fprintf(stderr, "end of compressed page with %u entries, %lu custom encodings because too many custom encodings\n", 
 
10396                                                                                         entryCount, pageSpecificEncodings.size());
 
10401                         encodingIndexes.push_back(encodingIndex);
 
10402                 // compute function offset
 
10403                 uint32_t funcOffsetWithInPage = lastEntryAddress - info.func->getAddress();
 
10404                 if ( funcOffsetWithInPage > 0x00FFFF00 ) {
 
10405                         // don't use 0x00FFFFFF because addresses may vary after atoms are laid out again
 
10406                         canDo = false; // case 2)
 
10407                         if (log) fprintf(stderr, "can't use compressed page with %u entries because function offset too big\n", entryCount);
 
10412                 // check room for entry
 
10413                 if ( (pageSpecificEncodings.size()+entryCount) >= space4 ) {
 
10414                         canDo = false; // case 1)
 
10416                         if (log) fprintf(stderr, "end of compressed page with %u entries because full\n", entryCount);
 
10418                 //if (log) fprintf(stderr, "space4=%d, pageSpecificEncodings.size()=%ld, entryCount=%d\n", space4, pageSpecificEncodings.size(), entryCount);
 
10421         // check for cases where it would be better to use a regular (non-compressed) page
 
10422         const unsigned int compressPageUsed = sizeof(unwind_info_compressed_second_level_page_header) 
 
10423                                                                 + pageSpecificEncodings.size()*sizeof(uint32_t)
 
10424                                                                 + entryCount*sizeof(uint32_t);
 
10425         if ( (compressPageUsed < (pageSize-4) && (index >= 0) ) ) {
 
10426                 const int regularEntriesPerPage = (pageSize - sizeof(unwind_info_regular_second_level_page_header))/sizeof(unwind_info_regular_second_level_entry);
 
10427                 if ( entryCount < regularEntriesPerPage ) {
 
10428                         return makeRegularSecondLevelPage(uniqueInfos, pageSize, endIndex, pageEnd);
 
10432         // check if we need any padding because adding another entry would take 8 bytes but only have room for 4
 
10434         if ( compressPageUsed == (pageSize-4) )
 
10437         // second pass fills in page 
 
10438         uint8_t* pageStart = pageEnd - compressPageUsed - pad;
 
10439         macho_unwind_info_compressed_second_level_page_header<P>* page = (macho_unwind_info_compressed_second_level_page_header<P>*)pageStart;
 
10440         page->set_kind(UNWIND_SECOND_LEVEL_COMPRESSED);
 
10441         page->set_entryPageOffset(sizeof(macho_unwind_info_compressed_second_level_page_header<P>));
 
10442         page->set_entryCount(entryCount);
 
10443         page->set_encodingsPageOffset(page->entryPageOffset()+entryCount*sizeof(uint32_t));
 
10444         page->set_encodingsCount(pageSpecificEncodings.size());
 
10445         uint32_t* const encodingsArray = (uint32_t*)&pageStart[page->encodingsPageOffset()];
 
10446         // fill in entry table
 
10447         uint32_t* const entiresArray = (uint32_t*)&pageStart[page->entryPageOffset()];
 
10448         ObjectFile::Atom* firstFunc = uniqueInfos[endIndex-entryCount].func;
 
10449         for(unsigned int i=endIndex-entryCount; i < endIndex; ++i) {
 
10450                 const Info& info = uniqueInfos[i];
 
10451                 uint8_t encodingIndex;
 
10452                 if ( encodingMeansUseDwarf(info.encoding) ) {
 
10453                         // dwarf entries are always in page specific encodings
 
10454                         encodingIndex = pageSpecificEncodings[info.encoding+i];
 
10457                         std::map<uint32_t, unsigned int>::const_iterator pos = commonEncodings.find(info.encoding);
 
10458                         if ( pos != commonEncodings.end() ) 
 
10459                                 encodingIndex = pos->second;
 
10461                                 encodingIndex = pageSpecificEncodings[info.encoding];
 
10463                 uint32_t entryIndex = i - endIndex + entryCount;
 
10464                 A::P::E::set32(entiresArray[entryIndex], encodingIndex << 24);
 
10465                 CompressedFixUp                 funcStartFixUp;
 
10466                 funcStartFixUp.contentPointer = (uint8_t*)(&entiresArray[entryIndex]);
 
10467                 funcStartFixUp.func = info.func;
 
10468                 funcStartFixUp.fromFunc = firstFunc;
 
10469                 fCompressedFixUps.push_back(funcStartFixUp);
 
10470                 if ( encodingMeansUseDwarf(info.encoding) ) {
 
10471                         CompressedEncodingFixUp dwarfStartFixup;
 
10472                         dwarfStartFixup.contentPointer = (uint8_t*)(&encodingsArray[encodingIndex-commonEncodings.size()]); 
 
10473                         dwarfStartFixup.fde = info.fde;
 
10474                         fCompressedEncodingFixUps.push_back(dwarfStartFixup);
 
10477         // fill in encodings table
 
10478         for(std::map<uint32_t, unsigned int>::const_iterator it = pageSpecificEncodings.begin(); it != pageSpecificEncodings.end(); ++it) {
 
10479                 A::P::E::set32(encodingsArray[it->second-commonEncodings.size()], it->first);
 
10482         if (log) fprintf(stderr, "compressed page with %u entries, %lu custom encodings\n", entryCount, pageSpecificEncodings.size());
 
10485         pageEnd = pageStart;
 
10486         return endIndex-entryCount;  // endIndex for next page
 
10489 template <> void UnwindInfoAtom<ppc>::generate() { }
 
10490 template <> void UnwindInfoAtom<ppc64>::generate() { }
 
10491 template <> void UnwindInfoAtom<arm>::generate() { }
 
10494 template <typename A>
 
10495 void UnwindInfoAtom<A>::generate()
 
10497         // only generate table if there are functions with unwind info
 
10498         if ( fInfos.size() > 0 ) {              
 
10499                 // find offset of end of __unwind_info section 
 
10500                 SectionInfo* unwindSectionInfo = (SectionInfo*)this->getSection();
 
10502                 // build new list that has proper offsetInImage and remove entries where next function has same encoding 
 
10503                 std::vector<Info> uniqueInfos;
 
10504                 this->compressDuplicates(uniqueInfos);
 
10506                 // build personality index, update encodings with personality index
 
10507                 this->makePersonalityIndex(uniqueInfos);
 
10508                 if ( fPersonalityIndexMap.size() > 3 )
 
10509                         throw "too many personality routines for compact unwind to encode";
 
10511                 // put the most common encodings into the common table, but at most 127 of them
 
10512                 std::map<uint32_t, unsigned int> commonEncodings;
 
10513                 this->findCommonEncoding(uniqueInfos, commonEncodings);
 
10515                 // build lsda index
 
10516                 std::map<ObjectFile::Atom*, uint32_t> lsdaIndexOffsetMap;
 
10517                 this->makeLsdaIndex(uniqueInfos, lsdaIndexOffsetMap);
 
10519                 // calculate worst case size for all unwind info pages when allocating buffer
 
10520                 const unsigned int entriesPerRegularPage = (4096-sizeof(unwind_info_regular_second_level_page_header))/sizeof(unwind_info_regular_second_level_entry);
 
10521                 const unsigned int pageCount = ((uniqueInfos.size() - 1)/entriesPerRegularPage) + 1;
 
10522                 fPagesContentForDelete = (uint8_t*)calloc(pageCount,4096);
 
10524                 if ( fPagesContentForDelete == NULL )
 
10525                         throw "could not allocate space for compact unwind info";
 
10526                 ObjectFile::Atom* secondLevelFirstFuncs[pageCount*3];
 
10527                 uint8_t* secondLevelPagesStarts[pageCount*3];
 
10529                 // make last second level page smaller so that all other second level pages can be page aligned
 
10530                 uint32_t maxLastPageSize = unwindSectionInfo->fFileOffset % 4096;
 
10531                 uint32_t tailPad = 0;
 
10532                 if ( maxLastPageSize < 128 ) {
 
10533                         tailPad = maxLastPageSize;
 
10534                         maxLastPageSize = 4096;
 
10537                 // fill in pages in reverse order
 
10538                 unsigned int endIndex = uniqueInfos.size();
 
10539                 unsigned int secondLevelPageCount = 0;
 
10540                 uint8_t* pageEnd = &fPagesContentForDelete[pageCount*4096];
 
10541                 uint32_t pageSize = maxLastPageSize;
 
10542                 while ( endIndex > 0 ) {
 
10543                         endIndex = makeCompressedSecondLevelPage(uniqueInfos, commonEncodings, pageSize, endIndex, pageEnd);
 
10544                         secondLevelPagesStarts[secondLevelPageCount] = pageEnd;
 
10545                         secondLevelFirstFuncs[secondLevelPageCount] = uniqueInfos[endIndex].func;
 
10546                         ++secondLevelPageCount;
 
10547                         pageSize = 4096;  // last page can be odd size, make rest up to 4096 bytes in size
 
10549                 fPagesContent = pageEnd;
 
10550                 fPagesSize = &fPagesContentForDelete[pageCount*4096] - pageEnd;
 
10552                 // calculate section layout
 
10553                 const uint32_t commonEncodingsArraySectionOffset = sizeof(macho_unwind_info_section_header<P>);
 
10554                 const uint32_t commonEncodingsArrayCount = commonEncodings.size();
 
10555                 const uint32_t commonEncodingsArraySize = commonEncodingsArrayCount * sizeof(compact_unwind_encoding_t);
 
10556                 const uint32_t personalityArraySectionOffset = commonEncodingsArraySectionOffset + commonEncodingsArraySize;
 
10557                 const uint32_t personalityArrayCount = fPersonalityIndexMap.size();
 
10558                 const uint32_t personalityArraySize = personalityArrayCount * sizeof(uint32_t);
 
10559                 const uint32_t indexSectionOffset = personalityArraySectionOffset + personalityArraySize;
 
10560                 const uint32_t indexCount = secondLevelPageCount+1;
 
10561                 const uint32_t indexSize = indexCount * sizeof(macho_unwind_info_section_header_index_entry<P>);
 
10562                 const uint32_t lsdaIndexArraySectionOffset = indexSectionOffset + indexSize;
 
10563                 const uint32_t lsdaIndexArrayCount = fLSDAIndex.size();
 
10564                 const uint32_t lsdaIndexArraySize = lsdaIndexArrayCount * sizeof(macho_unwind_info_section_header_lsda_index_entry<P>);
 
10565                 const uint32_t headerEndSectionOffset = lsdaIndexArraySectionOffset + lsdaIndexArraySize;
 
10568                 // allocate and fill in section header
 
10569                 fHeaderSize = headerEndSectionOffset;
 
10570                 fHeaderContent = new uint8_t[fHeaderSize];
 
10571                 bzero(fHeaderContent, fHeaderSize);
 
10572                 macho_unwind_info_section_header<P>* sectionHeader = (macho_unwind_info_section_header<P>*)fHeaderContent;
 
10573                 sectionHeader->set_version(UNWIND_SECTION_VERSION);
 
10574                 sectionHeader->set_commonEncodingsArraySectionOffset(commonEncodingsArraySectionOffset);
 
10575                 sectionHeader->set_commonEncodingsArrayCount(commonEncodingsArrayCount);
 
10576                 sectionHeader->set_personalityArraySectionOffset(personalityArraySectionOffset);
 
10577                 sectionHeader->set_personalityArrayCount(personalityArrayCount);
 
10578                 sectionHeader->set_indexSectionOffset(indexSectionOffset);
 
10579                 sectionHeader->set_indexCount(indexCount);
 
10581                 // copy common encodings
 
10582                 uint32_t* commonEncodingsTable = (uint32_t*)&fHeaderContent[commonEncodingsArraySectionOffset];
 
10583                 for (std::map<uint32_t, unsigned int>::iterator it=commonEncodings.begin(); it != commonEncodings.end(); ++it)
 
10584                         A::P::E::set32(commonEncodingsTable[it->second], it->first);
 
10586                 // make references for personality entries
 
10587                 uint32_t* personalityArray = (uint32_t*)&fHeaderContent[sectionHeader->personalityArraySectionOffset()];
 
10588                 for (std::map<ObjectFile::Atom*, unsigned int>::iterator it=fPersonalityIndexMap.begin(); it != fPersonalityIndexMap.end(); ++it) {
 
10589                         uint32_t offset = (uint8_t*)&personalityArray[it->second-1] - fHeaderContent;
 
10590                         fReferences.push_back(new WriterReference<A>(offset, A::kImageOffset32, it->first));
 
10593                 // build first level index and references
 
10594                 macho_unwind_info_section_header_index_entry<P>* indexTable = (macho_unwind_info_section_header_index_entry<P>*)&fHeaderContent[indexSectionOffset];
 
10595                 for (unsigned int i=0; i < secondLevelPageCount; ++i) {
 
10596                         unsigned int reverseIndex = secondLevelPageCount - 1 - i;
 
10597                         indexTable[i].set_functionOffset(0);
 
10598                         indexTable[i].set_secondLevelPagesSectionOffset(secondLevelPagesStarts[reverseIndex]-fPagesContent+headerEndSectionOffset);
 
10599                         indexTable[i].set_lsdaIndexArraySectionOffset(lsdaIndexOffsetMap[secondLevelFirstFuncs[reverseIndex]]+lsdaIndexArraySectionOffset); 
 
10600                         uint32_t refOffset = (uint8_t*)&indexTable[i] - fHeaderContent;
 
10601                         fReferences.push_back(new WriterReference<A>(refOffset, A::kImageOffset32, secondLevelFirstFuncs[reverseIndex]));
 
10603                 indexTable[secondLevelPageCount].set_functionOffset(0);
 
10604                 indexTable[secondLevelPageCount].set_secondLevelPagesSectionOffset(0);
 
10605                 indexTable[secondLevelPageCount].set_lsdaIndexArraySectionOffset(lsdaIndexArraySectionOffset+lsdaIndexArraySize); 
 
10606                 fReferences.push_back(new WriterReference<A>((uint8_t*)&indexTable[secondLevelPageCount] - fHeaderContent, A::kImageOffset32, 
 
10607                                                                                                                 fInfos.back().func, fInfos.back().func->getSize()+1));
 
10609                 // build lsda references
 
10610                 uint32_t lsdaEntrySectionOffset = lsdaIndexArraySectionOffset;
 
10611                 for (typename std::vector<LSDAEntry>::iterator it = fLSDAIndex.begin(); it != fLSDAIndex.end(); ++it) {
 
10612                         fReferences.push_back(new WriterReference<A>(lsdaEntrySectionOffset, A::kImageOffset32, it->func));
 
10613                         fReferences.push_back(new WriterReference<A>(lsdaEntrySectionOffset+4, A::kImageOffset32, it->lsda, it->lsdaOffset));
 
10614                         lsdaEntrySectionOffset += sizeof(unwind_info_section_header_lsda_index_entry);
 
10617                 // make references for regular second level entries
 
10618                 for (typename std::vector<RegFixUp>::iterator it = fRegFixUps.begin(); it != fRegFixUps.end(); ++it) {
 
10619                         uint32_t offset = (it->contentPointer - fPagesContent) + fHeaderSize;
 
10620                         fReferences.push_back(new WriterReference<A>(offset, A::kImageOffset32, it->func));
 
10621                         if ( it->fde != NULL )
 
10622                                 fReferences.push_back(new WriterReference<A>(offset+4, A::kSectionOffset24, it->fde));
 
10624                 // make references for compressed second level entries
 
10625                 for (typename std::vector<CompressedFixUp>::iterator it = fCompressedFixUps.begin(); it != fCompressedFixUps.end(); ++it) {
 
10626                         uint32_t offset = (it->contentPointer - fPagesContent) + fHeaderSize;
 
10627                         fReferences.push_back(new WriterReference<A>(offset, A::kPointerDiff24, it->func, 0, it->fromFunc, 0));
 
10629                 for (typename std::vector<CompressedEncodingFixUp>::iterator it = fCompressedEncodingFixUps.begin(); it != fCompressedEncodingFixUps.end(); ++it) {
 
10630                         uint32_t offset = (it->contentPointer - fPagesContent) + fHeaderSize;
 
10631                         fReferences.push_back(new WriterReference<A>(offset, A::kSectionOffset24, it->fde));
 
10634                 // update section record with new size
 
10635                 unwindSectionInfo->fSize = this->getSize();
 
10637                 // alter alignment so this section lays out so second level tables are page aligned
 
10638                 if ( secondLevelPageCount > 2 )
 
10639                         fAlignment = ObjectFile::Alignment(12, (unwindSectionInfo->fFileOffset - this->getSize()) % 4096);
 
10647 template <typename A>
 
10648 void UnwindInfoAtom<A>::copyRawContent(uint8_t buffer[]) const
 
10650         memcpy(buffer, fHeaderContent, fHeaderSize);
 
10651         memcpy(&buffer[fHeaderSize], fPagesContent, fPagesSize);
 
10656 template <typename A>
 
10657 uint64_t LinkEditAtom<A>::getFileOffset() const
 
10659         return ((SectionInfo*)this->getSection())->fFileOffset + this->getSectionOffset();
 
10663 template <typename A>
 
10664 uint64_t SectionRelocationsLinkEditAtom<A>::getSize() const
 
10666         return fWriter.fSectionRelocs.size() * sizeof(macho_relocation_info<P>);
 
10669 template <typename A>
 
10670 void SectionRelocationsLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
10672         memcpy(buffer, &fWriter.fSectionRelocs[0], this->getSize());
 
10676 template <typename A>
 
10677 uint64_t LocalRelocationsLinkEditAtom<A>::getSize() const
 
10679         return fWriter.fInternalRelocs.size() * sizeof(macho_relocation_info<P>);
 
10682 template <typename A>
 
10683 void LocalRelocationsLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
10685         memcpy(buffer, &fWriter.fInternalRelocs[0], this->getSize());
 
10690 template <typename A>
 
10691 uint64_t SymbolTableLinkEditAtom<A>::getSize() const
 
10693         return fWriter.fSymbolTableCount * sizeof(macho_nlist<P>);
 
10696 template <typename A>
 
10697 void SymbolTableLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
10699         memcpy(buffer, fWriter.fSymbolTable, this->getSize());
 
10702 template <typename A>
 
10703 uint64_t ExternalRelocationsLinkEditAtom<A>::getSize() const
 
10705         return fWriter.fExternalRelocs.size() * sizeof(macho_relocation_info<P>);
 
10708 template <typename A>
 
10709 void ExternalRelocationsLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
10711         std::sort(fWriter.fExternalRelocs.begin(), fWriter.fExternalRelocs.end(), ExternalRelocSorter<P>());
 
10712         memcpy(buffer, &fWriter.fExternalRelocs[0], this->getSize());
 
10717 template <typename A>
 
10718 uint64_t IndirectTableLinkEditAtom<A>::getSize() const
 
10720         return fTable.size() * sizeof(uint32_t);
 
10723 template <typename A>
 
10724 void IndirectTableLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
10726         uint64_t size = this->getSize();
 
10727         bzero(buffer, size);
 
10728         const uint32_t indirectTableSize = fTable.size();
 
10729         uint32_t* indirectTable = (uint32_t*)buffer;
 
10730         for(std::vector<IndirectEntry>::const_iterator it = fTable.begin(); it != fTable.end(); ++it) {
 
10731                 if ( it->indirectIndex < indirectTableSize )
 
10732                         A::P::E::set32(indirectTable[it->indirectIndex], it->symbolIndex);
 
10734                         throwf("malformed indirect table. size=%d, index=%d", indirectTableSize, it->indirectIndex);
 
10740 template <typename A>
 
10741 uint64_t ModuleInfoLinkEditAtom<A>::getSize() const
 
10743         return fWriter.fSymbolTableExportCount*sizeof(macho_dylib_table_of_contents<P>) 
 
10744                         + sizeof(macho_dylib_module<P>) 
 
10745                         + this->getReferencesCount()*sizeof(uint32_t);
 
10748 template <typename A>
 
10749 uint32_t ModuleInfoLinkEditAtom<A>::getTableOfContentsFileOffset() const
 
10751         return this->getFileOffset();
 
10754 template <typename A>
 
10755 uint32_t ModuleInfoLinkEditAtom<A>::getModuleTableFileOffset() const
 
10757         return this->getFileOffset() + fWriter.fSymbolTableExportCount*sizeof(macho_dylib_table_of_contents<P>);
 
10760 template <typename A>
 
10761 uint32_t ModuleInfoLinkEditAtom<A>::getReferencesFileOffset() const
 
10763         return this->getModuleTableFileOffset() + sizeof(macho_dylib_module<P>);
 
10766 template <typename A>
 
10767 uint32_t ModuleInfoLinkEditAtom<A>::getReferencesCount() const
 
10769         return fWriter.fSymbolTableExportCount + fWriter.fSymbolTableImportCount;
 
10772 template <typename A>
 
10773 void ModuleInfoLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
10775         uint64_t size = this->getSize();
 
10776         bzero(buffer, size);
 
10777         // create toc.  The symbols are already sorted, they are all in the smae module
 
10778         macho_dylib_table_of_contents<P>* p = (macho_dylib_table_of_contents<P>*)buffer;
 
10779         for(uint32_t i=0; i < fWriter.fSymbolTableExportCount; ++i, ++p) {
 
10780                 p->set_symbol_index(fWriter.fSymbolTableExportStartIndex+i);
 
10781                 p->set_module_index(0);
 
10783         // create module table (one entry)
 
10784         pint_t objcModuleSectionStart = 0;
 
10785         pint_t objcModuleSectionSize = 0;
 
10786         uint16_t numInits = 0;
 
10787         uint16_t numTerms = 0;
 
10788         std::vector<SegmentInfo*>& segmentInfos = fWriter.fSegmentInfos;
 
10789         for (std::vector<SegmentInfo*>::iterator segit = segmentInfos.begin(); segit != segmentInfos.end(); ++segit) {
 
10790                 std::vector<SectionInfo*>& sectionInfos = (*segit)->fSections;
 
10791                 if ( strcmp((*segit)->fName, "__DATA") == 0 ) {
 
10792                         for (std::vector<SectionInfo*>::iterator sectit = sectionInfos.begin(); sectit != sectionInfos.end(); ++sectit) {
 
10793                                 if ( strcmp((*sectit)->fSectionName, "__mod_init_func") == 0 ) 
 
10794                                         numInits = (*sectit)->fSize / sizeof(typename A::P::uint_t);
 
10795                                 else if ( strcmp((*sectit)->fSectionName, "__mod_term_func") == 0 ) 
 
10796                                         numTerms = (*sectit)->fSize / sizeof(typename A::P::uint_t);
 
10799                 else if ( strcmp((*segit)->fName, "__OBJC") == 0 ) {
 
10800                         for (std::vector<SectionInfo*>::iterator sectit = sectionInfos.begin(); sectit != sectionInfos.end(); ++sectit) {
 
10801                                 SectionInfo* sectInfo = (*sectit);
 
10802                                 if ( strcmp(sectInfo->fSectionName, "__module_info") == 0 ) {
 
10803                                         objcModuleSectionStart = sectInfo->getBaseAddress();
 
10804                                         objcModuleSectionSize  = sectInfo->fSize;
 
10809         macho_dylib_module<P>* module = (macho_dylib_module<P>*)&buffer[fWriter.fSymbolTableExportCount*sizeof(macho_dylib_table_of_contents<P>)];
 
10810         module->set_module_name(fModuleNameOffset);
 
10811         module->set_iextdefsym(fWriter.fSymbolTableExportStartIndex);
 
10812         module->set_nextdefsym(fWriter.fSymbolTableExportCount);
 
10813         module->set_irefsym(0);
 
10814         module->set_nrefsym(this->getReferencesCount());
 
10815         module->set_ilocalsym(fWriter.fSymbolTableStabsStartIndex);
 
10816         module->set_nlocalsym(fWriter.fSymbolTableStabsCount+fWriter.fSymbolTableLocalCount);
 
10817         module->set_iextrel(0);
 
10818         module->set_nextrel(fWriter.fExternalRelocs.size());
 
10819         module->set_iinit_iterm(0,0);
 
10820         module->set_ninit_nterm(numInits,numTerms);
 
10821         module->set_objc_module_info_addr(objcModuleSectionStart);      
 
10822         module->set_objc_module_info_size(objcModuleSectionSize);       
 
10823         // create reference table
 
10824         macho_dylib_reference<P>* ref = (macho_dylib_reference<P>*)((uint8_t*)module + sizeof(macho_dylib_module<P>));
 
10825         for(uint32_t i=0; i < fWriter.fSymbolTableExportCount; ++i, ++ref) {
 
10826                 ref->set_isym(fWriter.fSymbolTableExportStartIndex+i);
 
10827                 ref->set_flags(REFERENCE_FLAG_DEFINED);
 
10829         for(uint32_t i=0; i < fWriter.fSymbolTableImportCount; ++i, ++ref) {
 
10830                 ref->set_isym(fWriter.fSymbolTableImportStartIndex+i);
 
10831                 std::map<const ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fWriter.fStubsMap.find(fWriter.fImportedAtoms[i]);
 
10832                 if ( pos != fWriter.fStubsMap.end() )
 
10833                         ref->set_flags(REFERENCE_FLAG_UNDEFINED_LAZY);
 
10835                         ref->set_flags(REFERENCE_FLAG_UNDEFINED_NON_LAZY);
 
10841 template <typename A>
 
10842 StringsLinkEditAtom<A>::StringsLinkEditAtom(Writer<A>& writer)
 
10843         : LinkEditAtom<A>(writer), fCurrentBuffer(NULL), fCurrentBufferUsed(0)
 
10845         fCurrentBuffer = new char[kBufferSize];
 
10846         // burn first byte of string pool (so zero is never a valid string offset)
 
10847         fCurrentBuffer[fCurrentBufferUsed++] = ' ';
 
10848         // make offset 1 always point to an empty string
 
10849         fCurrentBuffer[fCurrentBufferUsed++] = '\0';
 
10852 template <typename A>
 
10853 uint64_t StringsLinkEditAtom<A>::getSize() const
 
10856         return (kBufferSize * fFullBuffers.size() + fCurrentBufferUsed + sizeof(typename A::P::uint_t) - 1) & (-sizeof(typename A::P::uint_t));
 
10859 template <typename A>
 
10860 void StringsLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
10862         uint64_t offset = 0;
 
10863         for (unsigned int i=0; i < fFullBuffers.size(); ++i) {
 
10864                 memcpy(&buffer[offset], fFullBuffers[i], kBufferSize);
 
10865                 offset += kBufferSize;
 
10867         memcpy(&buffer[offset], fCurrentBuffer, fCurrentBufferUsed);
 
10868         // zero fill end to align
 
10869         offset += fCurrentBufferUsed;
 
10870         while ( (offset % sizeof(typename A::P::uint_t)) != 0 )
 
10871                 buffer[offset++] = 0;
 
10874 template <typename A>
 
10875 int32_t StringsLinkEditAtom<A>::add(const char* name)
 
10877         int32_t offset = kBufferSize * fFullBuffers.size() + fCurrentBufferUsed;
 
10878         int lenNeeded = strlcpy(&fCurrentBuffer[fCurrentBufferUsed], name, kBufferSize-fCurrentBufferUsed)+1;
 
10879         if ( (fCurrentBufferUsed+lenNeeded) < kBufferSize ) {
 
10880                 fCurrentBufferUsed += lenNeeded;
 
10883                 int copied = kBufferSize-fCurrentBufferUsed-1;
 
10884                 // change trailing '\0' that strlcpy added to real char
 
10885                 fCurrentBuffer[kBufferSize-1] = name[copied];
 
10886                 // alloc next buffer
 
10887                 fFullBuffers.push_back(fCurrentBuffer);
 
10888                 fCurrentBuffer = new char[kBufferSize];
 
10889                 fCurrentBufferUsed = 0;
 
10890                 // append rest of string
 
10891                 this->add(&name[copied+1]);
 
10897 template <typename A>
 
10898 int32_t StringsLinkEditAtom<A>::addUnique(const char* name)
 
10900         StringToOffset::iterator pos = fUniqueStrings.find(name);
 
10901         if ( pos != fUniqueStrings.end() ) {
 
10902                 return pos->second;
 
10905                 int32_t offset = this->add(name);
 
10906                 fUniqueStrings[name] = offset;
 
10912 template <typename A>
 
10913 const char* StringsLinkEditAtom<A>::stringForIndex(int32_t index) const
 
10915         int32_t currentBufferStartIndex = kBufferSize * fFullBuffers.size();
 
10916         int32_t maxIndex = currentBufferStartIndex + fCurrentBufferUsed;
 
10917         // check for out of bounds
 
10918         if ( index > maxIndex )
 
10920         // check for index in fCurrentBuffer
 
10921         if ( index > currentBufferStartIndex )
 
10922                 return &fCurrentBuffer[index-currentBufferStartIndex];
 
10923         // otherwise index is in a full buffer
 
10924         uint32_t fullBufferIndex = index/kBufferSize;
 
10925         return &fFullBuffers[fullBufferIndex][index-(kBufferSize*fullBufferIndex)];
 
10930 template <typename A>
 
10931 BranchIslandAtom<A>::BranchIslandAtom(Writer<A>& writer, const char* name, int islandRegion, ObjectFile::Atom& target, 
 
10932                                                                                         ObjectFile::Atom& finalTarget, uint32_t finalTargetOffset)
 
10933  : WriterAtom<A>(writer, Segment::fgTextSegment), fTarget(target), fFinalTarget(finalTarget), fFinalTargetOffset(finalTargetOffset)
 
10935         if ( finalTargetOffset == 0 ) {
 
10936                 if ( islandRegion == 0 )
 
10937                         asprintf((char**)&fName, "%s$island", name);
 
10939                         asprintf((char**)&fName, "%s$island$%d", name, islandRegion+1);
 
10942                 asprintf((char**)&fName, "%s_plus_%d$island$%d", name, finalTargetOffset, islandRegion);
 
10945         if ( finalTarget.isThumb() ) {
 
10946                 if ( writer.fOptions.preferSubArchitecture() && writer.fOptions.subArchitecture() == CPU_SUBTYPE_ARM_V7 ) {
 
10947                         fIslandKind = kBranchIslandToThumb2;
 
10950                         fIslandKind = kBranchIslandToThumb1;
 
10954                 fIslandKind = kBranchIslandToARM;
 
10960 void BranchIslandAtom<ppc>::copyRawContent(uint8_t buffer[]) const
 
10962         int64_t displacement;
 
10963         const int64_t bl_sixteenMegLimit = 0x00FFFFFF;
 
10964         if ( fTarget.getContentType() == ObjectFile::Atom::kBranchIsland ) {
 
10965                 displacement = getFinalTargetAdress() - this->getAddress();
 
10966                 if ( (displacement > bl_sixteenMegLimit) && (displacement < (-bl_sixteenMegLimit)) ) {
 
10967                         displacement = fTarget.getAddress() - this->getAddress();
 
10971                 displacement = fTarget.getAddress() + fFinalTargetOffset - this->getAddress();
 
10973         int32_t branchInstruction = 0x48000000 | ((uint32_t)displacement & 0x03FFFFFC);
 
10974         OSWriteBigInt32(buffer, 0, branchInstruction);
 
10978 void BranchIslandAtom<ppc64>::copyRawContent(uint8_t buffer[]) const
 
10980         int64_t displacement;
 
10981         const int64_t bl_sixteenMegLimit = 0x00FFFFFF;
 
10982         if ( fTarget.getContentType() == ObjectFile::Atom::kBranchIsland ) {
 
10983                 displacement = getFinalTargetAdress() - this->getAddress();
 
10984                 if ( (displacement > bl_sixteenMegLimit) && (displacement < (-bl_sixteenMegLimit)) ) {
 
10985                         displacement = fTarget.getAddress() - this->getAddress();
 
10989                 displacement = fTarget.getAddress() + fFinalTargetOffset - this->getAddress();
 
10991         int32_t branchInstruction = 0x48000000 | ((uint32_t)displacement & 0x03FFFFFC);
 
10992         OSWriteBigInt32(buffer, 0, branchInstruction);
 
10996 void BranchIslandAtom<arm>::copyRawContent(uint8_t buffer[]) const
 
10998         const bool log = false;
 
10999         switch ( fIslandKind ) {
 
11000                 case kBranchIslandToARM:
 
11002                         int64_t displacement;
 
11003                         // an ARM branch can branch farther than a thumb branch.  The branch
 
11004                         // island generation was conservative and put islands every thumb
 
11005                         // branch distance apart.  Check to see if this is a an island
 
11006                         // hopping branch that could be optimized to go directly to target.
 
11007                         if ( fTarget.getContentType() == ObjectFile::Atom::kBranchIsland ) {
 
11008                                 displacement = getFinalTargetAdress() - this->getAddress() - 8;
 
11009                                 if ( (displacement < 33554428LL) && (displacement > (-33554432LL)) ) {
 
11010                                         // can skip branch island and jump straight to target
 
11011                                         if (log) fprintf(stderr, "%s: optimized jump to final target at 0x%08llX, thisAddr=0x%08llX\n", fName, getFinalTargetAdress(), this->getAddress());
 
11014                                         // ultimate target is too far, jump to island
 
11015                                         displacement = fTarget.getAddress() - this->getAddress() - 8;
 
11016                                         if (log) fprintf(stderr, "%s: jump to branch island at 0x%08llX\n", fName, fTarget.getAddress());
 
11020                                 // target of island is ultimate target
 
11021                                 displacement = fTarget.getAddress() + fFinalTargetOffset - this->getAddress() - 8;
 
11022                                 if (log) fprintf(stderr, "%s: jump to target at 0x%08llX\n", fName, fTarget.getAddress());
 
11024                         uint32_t imm24 = (displacement >> 2) & 0x00FFFFFF;
 
11025                         int32_t branchInstruction = 0xEA000000 | imm24;
 
11026                         OSWriteLittleInt32(buffer, 0, branchInstruction);
 
11029                 case kBranchIslandToThumb2:
 
11031                         int64_t displacement;
 
11032                         // an ARM branch can branch farther than a thumb branch.  The branch
 
11033                         // island generation was conservative and put islands every thumb
 
11034                         // branch distance apart.  Check to see if this is a an island
 
11035                         // hopping branch that could be optimized to go directly to target.
 
11036                         if ( fTarget.getContentType() == ObjectFile::Atom::kBranchIsland ) {
 
11037                                 displacement = getFinalTargetAdress() - this->getAddress() - 4;
 
11038                                 if ( (displacement < 16777214) && (displacement > (-16777216LL)) ) {
 
11039                                         // can skip branch island and jump straight to target
 
11040                                         if (log) fprintf(stderr, "%s: optimized jump to final target at 0x%08llX, thisAddr=0x%08llX\n", fName, getFinalTargetAdress(), this->getAddress());
 
11043                                         // ultimate target is too far, jump to island
 
11044                                         displacement = fTarget.getAddress() - this->getAddress() - 4;
 
11045                                         if (log) fprintf(stderr, "%s: jump to branch island at 0x%08llX\n", fName, fTarget.getAddress());
 
11049                                 // target of island is ultimate target
 
11050                                 displacement = fTarget.getAddress() + fFinalTargetOffset - this->getAddress() - 4;
 
11051                                 if (log) fprintf(stderr, "%s: jump to target at 0x%08llX\n", fName, fTarget.getAddress());
 
11053                         if ( (displacement > 16777214) || (displacement < (-16777216LL)) ) {
 
11054                                 throwf("internal branch island error: thumb2 b/bx out of range (%lld max is +/-16M) from %s to %s in %s",
 
11055                                                 displacement, this->getDisplayName(), 
 
11056                                                 fTarget.getDisplayName(), fTarget.getFile()->getPath());
 
11058                         // The instruction is really two instructions:
 
11059                         // The lower 16 bits are the first instruction, which contains the high
 
11060                         //   11 bits of the displacement.
 
11061                         // The upper 16 bits are the second instruction, which contains the low
 
11062                         //   11 bits of the displacement, as well as differentiating bl and blx.
 
11063                         uint32_t s = (uint32_t)(displacement >> 24) & 0x1;
 
11064                         uint32_t i1 = (uint32_t)(displacement >> 23) & 0x1;
 
11065                         uint32_t i2 = (uint32_t)(displacement >> 22) & 0x1;
 
11066                         uint32_t imm10 = (uint32_t)(displacement >> 12) & 0x3FF;
 
11067                         uint32_t imm11 = (uint32_t)(displacement >> 1) & 0x7FF;
 
11068                         uint32_t j1 = (i1 == s);
 
11069                         uint32_t j2 = (i2 == s);
 
11070                         uint32_t opcode = 0x9000F000;
 
11071                         uint32_t nextDisp = (j1 << 13) | (j2 << 11) | imm11;
 
11072                         uint32_t firstDisp = (s << 10) | imm10;
 
11073                         uint32_t newInstruction = opcode | (nextDisp << 16) | firstDisp;
 
11074                         //warning("s=%d, j1=%d, j2=%d, imm10=0x%0X, imm11=0x%0X, opcode=0x%08X, first=0x%04X, next=0x%04X, new=0x%08X, disp=0x%llX for %s to %s\n",
 
11075                         //      s, j1, j2, imm10, imm11, opcode, firstDisp, nextDisp, newInstruction, displacement, inAtom->getDisplayName(), ref->getTarget().getDisplayName());
 
11076                         OSWriteLittleInt32(buffer, 0, newInstruction);
 
11079                 case kBranchIslandToThumb1:
 
11081                         // There is no large displacement thumb1 branch instruction.
 
11082                         // Instead use ARM instructions that can jump to thumb.
 
11083                         // we use a 32-bit displacement, so we can directly jump to target which means no island hopping
 
11084                         int64_t displacement = getFinalTargetAdress() - (this->getAddress() + 12);
 
11085                         if ( fFinalTarget.isThumb() )
 
11087                         if (log) fprintf(stderr, "%s: 4 ARM instruction jump to final target at 0x%08llX\n", fName, getFinalTargetAdress());
 
11088                         OSWriteLittleInt32(&buffer[ 0], 0, 0xe59fc004); //      ldr  ip, pc + 4
 
11089                         OSWriteLittleInt32(&buffer[ 4], 0, 0xe08fc00c); //      add      ip, pc, ip
 
11090                         OSWriteLittleInt32(&buffer[ 8], 0, 0xe12fff1c); //      bx       ip
 
11091                         OSWriteLittleInt32(&buffer[12], 0, displacement);       //      .long target-this               
 
11098 uint64_t BranchIslandAtom<ppc>::getSize() const
 
11104 uint64_t BranchIslandAtom<ppc64>::getSize() const
 
11110 uint64_t BranchIslandAtom<arm>::getSize() const
 
11112         switch ( fIslandKind ) {
 
11113                 case kBranchIslandToARM:
 
11115                 case kBranchIslandToThumb1:
 
11117                 case kBranchIslandToThumb2:
 
11120         throw "internal error: no ARM branch island kind";
 
11125 template <typename A>
 
11126 uint64_t SegmentSplitInfoLoadCommandsAtom<A>::getSize() const
 
11128         if ( fWriter.fSplitCodeToDataContentAtom->canEncode() )
 
11129                 return this->alignedSize(sizeof(macho_linkedit_data_command<P>));
 
11131                 return 0;       // a zero size causes the load command to be suppressed
 
11134 template <typename A>
 
11135 void SegmentSplitInfoLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
11137         uint64_t size = this->getSize();
 
11139                 bzero(buffer, size);
 
11140                 macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)buffer;
 
11141                 cmd->set_cmd(LC_SEGMENT_SPLIT_INFO);
 
11142                 cmd->set_cmdsize(size);
 
11143                 cmd->set_dataoff(fWriter.fSplitCodeToDataContentAtom->getFileOffset());
 
11144                 cmd->set_datasize(fWriter.fSplitCodeToDataContentAtom->getSize());
 
11149 template <typename A>
 
11150 uint64_t SegmentSplitInfoContentAtom<A>::getSize() const
 
11152         return fEncodedData.size();
 
11155 template <typename A>
 
11156 void SegmentSplitInfoContentAtom<A>::copyRawContent(uint8_t buffer[]) const
 
11158         memcpy(buffer, &fEncodedData[0], fEncodedData.size());
 
11162 template <typename A>
 
11163 void SegmentSplitInfoContentAtom<A>::uleb128EncodeAddresses(const std::vector<SegmentSplitInfoContentAtom<A>::AtomAndOffset>& locations)
 
11165         pint_t addr = fWriter.fOptions.baseAddress();
 
11166         for(typename std::vector<AtomAndOffset>::const_iterator it = locations.begin(); it != locations.end(); ++it) {
 
11167                 pint_t nextAddr = it->atom->getAddress() + it->offset;
 
11168                 //fprintf(stderr, "\t0x%0llX\n", (uint64_t)nextAddr);
 
11169                 uint64_t delta = nextAddr - addr;
 
11171                         throw "double split seg info for same address";
 
11175                         byte = delta & 0x7F;
 
11179                         fEncodedData.push_back(byte);
 
11180                         delta = delta >> 7;
 
11182                 while( byte >= 0x80 );
 
11187 template <typename A>
 
11188 void SegmentSplitInfoContentAtom<A>::encode()
 
11190         if ( ! fCantEncode ) {
 
11191                 fEncodedData.reserve(8192);
 
11193                 if ( fKind1Locations.size() != 0 ) {
 
11194                         fEncodedData.push_back(1);
 
11195                         //fprintf(stderr, "type 1:\n");
 
11196                         this->uleb128EncodeAddresses(fKind1Locations);
 
11197                         fEncodedData.push_back(0);
 
11200                 if ( fKind2Locations.size() != 0 ) {
 
11201                         fEncodedData.push_back(2);
 
11202                         //fprintf(stderr, "type 2:\n");
 
11203                         this->uleb128EncodeAddresses(fKind2Locations);
 
11204                         fEncodedData.push_back(0);
 
11207                 if ( fKind3Locations.size() != 0 ) {
 
11208                         fEncodedData.push_back(3);
 
11209                         //fprintf(stderr, "type 3:\n");
 
11210                         this->uleb128EncodeAddresses(fKind3Locations);
 
11211                         fEncodedData.push_back(0);
 
11214                 if ( fKind4Locations.size() != 0 ) {
 
11215                         fEncodedData.push_back(4);
 
11216                         //fprintf(stderr, "type 4:\n");
 
11217                         this->uleb128EncodeAddresses(fKind4Locations);
 
11218                         fEncodedData.push_back(0);
 
11221                 // always add zero byte to mark end
 
11222                 fEncodedData.push_back(0);
 
11224                 // add zeros to end to align size
 
11225                 while ( (fEncodedData.size() % sizeof(pint_t)) != 0 )
 
11226                         fEncodedData.push_back(0);
 
11231 template <typename A>
 
11232 ObjCInfoAtom<A>::ObjCInfoAtom(Writer<A>& writer, ObjectFile::Reader::ObjcConstraint objcConstraint, bool objcReplacementClasses)
 
11233         : WriterAtom<A>(writer, getInfoSegment())
 
11236         uint32_t value = 0;
 
11237         //      struct objc_image_info  {
 
11238         //              uint32_t        version;        // initially 0
 
11241         // #define OBJC_IMAGE_SUPPORTS_GC   2
 
11242         // #define OBJC_IMAGE_GC_ONLY       4
 
11244         if ( objcReplacementClasses ) 
 
11246         switch ( objcConstraint ) {
 
11247                 case ObjectFile::Reader::kObjcNone:
 
11248                 case ObjectFile::Reader::kObjcRetainRelease:
 
11250                 case ObjectFile::Reader::kObjcRetainReleaseOrGC:
 
11253                 case ObjectFile::Reader::kObjcGC:
 
11257         A::P::E::set32(fContent[1], value);
 
11260 template <typename A>
 
11261 void ObjCInfoAtom<A>::copyRawContent(uint8_t buffer[]) const
 
11263         memcpy(buffer, &fContent[0], 8);
 
11267 // objc info section is in a different segment and section for 32 vs 64 bit runtimes
 
11268 template <> const char* ObjCInfoAtom<ppc>::getSectionName()    const { return "__image_info"; }
 
11269 template <> const char* ObjCInfoAtom<x86>::getSectionName()    const { return "__image_info"; }
 
11270 template <> const char* ObjCInfoAtom<arm>::getSectionName()    const { return "__objc_imageinfo"; }
 
11271 template <> const char* ObjCInfoAtom<ppc64>::getSectionName()  const { return "__objc_imageinfo"; }
 
11272 template <> const char* ObjCInfoAtom<x86_64>::getSectionName() const { return "__objc_imageinfo"; }
 
11274 template <> Segment& ObjCInfoAtom<ppc>::getInfoSegment()    const { return Segment::fgObjCSegment; }
 
11275 template <> Segment& ObjCInfoAtom<x86>::getInfoSegment()    const { return Segment::fgObjCSegment; }
 
11276 template <> Segment& ObjCInfoAtom<ppc64>::getInfoSegment()  const { return Segment::fgDataSegment; }
 
11277 template <> Segment& ObjCInfoAtom<x86_64>::getInfoSegment() const { return Segment::fgDataSegment; }
 
11278 template <> Segment& ObjCInfoAtom<arm>::getInfoSegment()    const { return Segment::fgDataSegment; }
 
11283 template <typename A>
 
11284 void DyldInfoLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
11286         // build LC_DYLD_INFO command
 
11287         macho_dyld_info_command<P>*  cmd = (macho_dyld_info_command<P>*)buffer;
 
11288         bzero(cmd, sizeof(macho_dyld_info_command<P>));
 
11290         cmd->set_cmd( fWriter.fOptions.makeClassicDyldInfo() ? LC_DYLD_INFO : LC_DYLD_INFO_ONLY);
 
11291         cmd->set_cmdsize(sizeof(macho_dyld_info_command<P>));
 
11292         if ( (fWriter.fCompressedRebaseInfoAtom != NULL) && (fWriter.fCompressedRebaseInfoAtom->getSize() != 0) ) {
 
11293                 cmd->set_rebase_off(fWriter.fCompressedRebaseInfoAtom->getFileOffset());
 
11294                 cmd->set_rebase_size(fWriter.fCompressedRebaseInfoAtom->getSize());
 
11296         if ( (fWriter.fCompressedBindingInfoAtom != NULL) && (fWriter.fCompressedBindingInfoAtom->getSize() != 0) ) {
 
11297                 cmd->set_bind_off(fWriter.fCompressedBindingInfoAtom->getFileOffset());
 
11298                 cmd->set_bind_size(fWriter.fCompressedBindingInfoAtom->getSize());
 
11300         if ( (fWriter.fCompressedWeakBindingInfoAtom != NULL) && (fWriter.fCompressedWeakBindingInfoAtom->getSize() != 0) ) {
 
11301                 cmd->set_weak_bind_off(fWriter.fCompressedWeakBindingInfoAtom->getFileOffset());
 
11302                 cmd->set_weak_bind_size(fWriter.fCompressedWeakBindingInfoAtom->getSize());
 
11304         if ( (fWriter.fCompressedLazyBindingInfoAtom != NULL) && (fWriter.fCompressedLazyBindingInfoAtom->getSize() != 0) ) {
 
11305                 cmd->set_lazy_bind_off(fWriter.fCompressedLazyBindingInfoAtom->getFileOffset());
 
11306                 cmd->set_lazy_bind_size(fWriter.fCompressedLazyBindingInfoAtom->getSize());
 
11308         if ( (fWriter.fCompressedExportInfoAtom != NULL) && (fWriter.fCompressedExportInfoAtom->getSize() != 0) ) {
 
11309                 cmd->set_export_off(fWriter.fCompressedExportInfoAtom->getFileOffset());
 
11310                 cmd->set_export_size(fWriter.fCompressedExportInfoAtom->getSize());
 
11317         rebase_tmp(uint8_t op, uint64_t p1, uint64_t p2=0) : opcode(op), operand1(p1), operand2(p2) {}
 
11324 template <typename A>
 
11325 void CompressedRebaseInfoLinkEditAtom<A>::encode()
 
11327         // sort rebase info by type, then address
 
11328         const std::vector<SegmentInfo*>& segments = fWriter.fSegmentInfos;
 
11329         std::vector<RebaseInfo>& info = fWriter.fRebaseInfo;
 
11330         std::sort(info.begin(), info.end());
 
11332         // convert to temp encoding that can be more easily optimized
 
11333         std::vector<rebase_tmp> mid;
 
11334         const SegmentInfo* currentSegment = NULL;
 
11335         unsigned int segIndex = 0;
 
11337         uint64_t address = (uint64_t)(-1);
 
11338         for (std::vector<RebaseInfo>::iterator it = info.begin(); it != info.end(); ++it) {
 
11339                 if ( type != it->fType ) {
 
11340                         mid.push_back(rebase_tmp(REBASE_OPCODE_SET_TYPE_IMM, it->fType));
 
11343                 if ( address != it->fAddress ) {
 
11344                         if ( (currentSegment == NULL) || (it->fAddress < currentSegment->fBaseAddress) 
 
11345                                         || ((currentSegment->fBaseAddress+currentSegment->fSize) <= it->fAddress) ) {
 
11347                                 for (std::vector<SegmentInfo*>::const_iterator segit = segments.begin(); segit != segments.end(); ++segit) {
 
11348                                         if ( ((*segit)->fBaseAddress <= it->fAddress) && (it->fAddress < ((*segit)->fBaseAddress+(*segit)->fSize)) ) {
 
11349                                                 currentSegment = *segit;
 
11354                                 mid.push_back(rebase_tmp(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, segIndex, it->fAddress - currentSegment->fBaseAddress));
 
11357                                 mid.push_back(rebase_tmp(REBASE_OPCODE_ADD_ADDR_ULEB, it->fAddress-address));
 
11359                         address = it->fAddress;
 
11361                 mid.push_back(rebase_tmp(REBASE_OPCODE_DO_REBASE_ULEB_TIMES, 1));
 
11362                 address += sizeof(pint_t);
 
11364         mid.push_back(rebase_tmp(REBASE_OPCODE_DONE, 0));
 
11366         // optimize phase 1, compress packed runs of pointers
 
11367         rebase_tmp* dst = &mid[0];
 
11368         for (const rebase_tmp* src = &mid[0]; src->opcode != REBASE_OPCODE_DONE; ++src) {
 
11369                 if ( (src->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES) && (src->operand1 == 1) ) {
 
11371                         while (src->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES ) {
 
11372                                 dst->operand1 += src->operand1;
 
11382         dst->opcode = REBASE_OPCODE_DONE;
 
11384         // optimize phase 2, combine rebase/add pairs
 
11386         for (const rebase_tmp* src = &mid[0]; src->opcode != REBASE_OPCODE_DONE; ++src) {
 
11387                 if ( (src->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES) 
 
11388                                 && (src->operand1 == 1) 
 
11389                                 && (src[1].opcode == REBASE_OPCODE_ADD_ADDR_ULEB)) {
 
11390                         dst->opcode = REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB;
 
11391                         dst->operand1 = src[1].operand1;
 
11399         dst->opcode = REBASE_OPCODE_DONE;
 
11401         // optimize phase 3, compress packed runs of REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB with
 
11402         // same addr delta into one REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB
 
11404         for (const rebase_tmp* src = &mid[0]; src->opcode != REBASE_OPCODE_DONE; ++src) {
 
11405                 uint64_t delta = src->operand1;
 
11406                 if ( (src->opcode == REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB) 
 
11407                                 && (src[1].opcode == REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB) 
 
11408                                 && (src[2].opcode == REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB) 
 
11409                                 && (src[1].operand1 == delta) 
 
11410                                 && (src[2].operand1 == delta) ) {
 
11411                         // found at least three in a row, this is worth compressing
 
11412                         dst->opcode = REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB;
 
11414                         dst->operand2 = delta;
 
11416                         while ( (src->opcode == REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB)
 
11417                                         && (src->operand1 == delta) ) {
 
11428         dst->opcode = REBASE_OPCODE_DONE;
 
11430         // optimize phase 4, use immediate encodings
 
11431         for (rebase_tmp* p = &mid[0]; p->opcode != REBASE_OPCODE_DONE; ++p) {
 
11432                 if ( (p->opcode == REBASE_OPCODE_ADD_ADDR_ULEB) 
 
11433                         && (p->operand1 < (15*sizeof(pint_t)))
 
11434                         && ((p->operand1 % sizeof(pint_t)) == 0) ) {
 
11435                         p->opcode = REBASE_OPCODE_ADD_ADDR_IMM_SCALED;
 
11436                         p->operand1 = p->operand1/sizeof(pint_t);
 
11438                 else if ( (p->opcode == REBASE_OPCODE_DO_REBASE_ULEB_TIMES) && (p->operand1 < 15) ) {
 
11439                         p->opcode = REBASE_OPCODE_DO_REBASE_IMM_TIMES;
 
11443         // convert to compressed encoding
 
11444         const static bool log = false;
 
11445         fEncodedData.reserve(info.size()*2);
 
11447         for (std::vector<rebase_tmp>::iterator it = mid.begin(); !done && it != mid.end() ; ++it) {
 
11448                 switch ( it->opcode ) {
 
11449                         case REBASE_OPCODE_DONE:
 
11450                                 if ( log ) fprintf(stderr, "REBASE_OPCODE_DONE()\n");
 
11453                         case REBASE_OPCODE_SET_TYPE_IMM:
 
11454                                 if ( log ) fprintf(stderr, "REBASE_OPCODE_SET_TYPE_IMM(%lld)\n", it->operand1);
 
11455                                 fEncodedData.append_byte(REBASE_OPCODE_SET_TYPE_IMM | it->operand1);
 
11457                         case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
 
11458                                 if ( log ) fprintf(stderr, "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(%lld, 0x%llX)\n", it->operand1, it->operand2);
 
11459                                 fEncodedData.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | it->operand1);
 
11460                                 fEncodedData.append_uleb128(it->operand2);
 
11462                         case REBASE_OPCODE_ADD_ADDR_ULEB:
 
11463                                 if ( log ) fprintf(stderr, "REBASE_OPCODE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
 
11464                                 fEncodedData.append_byte(REBASE_OPCODE_ADD_ADDR_ULEB);
 
11465                                 fEncodedData.append_uleb128(it->operand1);
 
11467                         case REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
 
11468                                 if ( log ) fprintf(stderr, "REBASE_OPCODE_ADD_ADDR_IMM_SCALED(%lld=0x%llX)\n", it->operand1, it->operand1*sizeof(pint_t));
 
11469                                 fEncodedData.append_byte(REBASE_OPCODE_ADD_ADDR_IMM_SCALED | it->operand1 );
 
11471                         case REBASE_OPCODE_DO_REBASE_IMM_TIMES:
 
11472                                 if ( log ) fprintf(stderr, "REBASE_OPCODE_DO_REBASE_IMM_TIMES(%lld)\n", it->operand1);
 
11473                                 fEncodedData.append_byte(REBASE_OPCODE_DO_REBASE_IMM_TIMES | it->operand1);
 
11475                         case REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
 
11476                                 if ( log ) fprintf(stderr, "REBASE_OPCODE_DO_REBASE_ULEB_TIMES(%lld)\n", it->operand1);
 
11477                                 fEncodedData.append_byte(REBASE_OPCODE_DO_REBASE_ULEB_TIMES);
 
11478                                 fEncodedData.append_uleb128(it->operand1);
 
11480                         case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
 
11481                                 if ( log ) fprintf(stderr, "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
 
11482                                 fEncodedData.append_byte(REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB);
 
11483                                 fEncodedData.append_uleb128(it->operand1);
 
11485                         case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
 
11486                                 if ( log ) fprintf(stderr, "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB(%lld, %lld)\n", it->operand1, it->operand2);
 
11487                                 fEncodedData.append_byte(REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB);
 
11488                                 fEncodedData.append_uleb128(it->operand1);
 
11489                                 fEncodedData.append_uleb128(it->operand2);
 
11495         // align to pointer size
 
11496         fEncodedData.pad_to_size(sizeof(pint_t));
 
11498         if (log) fprintf(stderr, "total rebase info size = %ld\n", fEncodedData.size());
 
11504         binding_tmp(uint8_t op, uint64_t p1, uint64_t p2=0, const char* s=NULL) 
 
11505                 : opcode(op), operand1(p1), operand2(p2), name(s) {}
 
11514 template <typename A>
 
11515 void CompressedBindingInfoLinkEditAtom<A>::encode()
 
11517         // sort by library, symbol, type, then address
 
11518         const std::vector<SegmentInfo*>& segments = fWriter.fSegmentInfos;
 
11519         std::vector<BindingInfo>& info = fWriter.fBindingInfo;
 
11520         std::sort(info.begin(), info.end());
 
11522         // convert to temp encoding that can be more easily optimized
 
11523         std::vector<binding_tmp> mid;
 
11524         const SegmentInfo* currentSegment = NULL;
 
11525         unsigned int segIndex = 0;
 
11526         int ordinal = 0x80000000;
 
11527         const char* symbolName = NULL;
 
11529         uint64_t address = (uint64_t)(-1);
 
11530         int64_t addend = 0;
 
11531         for (std::vector<BindingInfo>::iterator it = info.begin(); it != info.end(); ++it) {
 
11532                 if ( ordinal != it->fLibraryOrdinal ) {
 
11533                         if ( it->fLibraryOrdinal <= 0 ) {
 
11534                                 // special lookups are encoded as negative numbers in BindingInfo
 
11535                                 mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM, it->fLibraryOrdinal));
 
11538                                 mid.push_back(binding_tmp(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB, it->fLibraryOrdinal));
 
11540                         ordinal = it->fLibraryOrdinal;
 
11542                 if ( symbolName != it->fSymbolName ) {
 
11543                         mid.push_back(binding_tmp(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM, it->fFlags, 0, it->fSymbolName));
 
11544                         symbolName = it->fSymbolName;
 
11546                 if ( type != it->fType ) {
 
11547                         mid.push_back(binding_tmp(BIND_OPCODE_SET_TYPE_IMM, it->fType));
 
11550                 if ( address != it->fAddress ) {
 
11551                         if ( (currentSegment == NULL) || (it->fAddress < currentSegment->fBaseAddress) 
 
11552                                         || ((currentSegment->fBaseAddress+currentSegment->fSize) <=it->fAddress) 
 
11553                                         || (it->fAddress < address) ) {
 
11555                                 for (std::vector<SegmentInfo*>::const_iterator segit = segments.begin(); segit != segments.end(); ++segit) {
 
11556                                         if ( ((*segit)->fBaseAddress <= it->fAddress) && (it->fAddress < ((*segit)->fBaseAddress+(*segit)->fSize)) ) {
 
11557                                                 currentSegment = *segit;
 
11562                                 mid.push_back(binding_tmp(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, segIndex, it->fAddress - currentSegment->fBaseAddress));
 
11565                                 mid.push_back(binding_tmp(BIND_OPCODE_ADD_ADDR_ULEB, it->fAddress-address));
 
11567                         address = it->fAddress;
 
11569                 if ( addend != it->fAddend ) {
 
11570                         mid.push_back(binding_tmp(BIND_OPCODE_SET_ADDEND_SLEB, it->fAddend));
 
11571                         addend = it->fAddend;
 
11573                 mid.push_back(binding_tmp(BIND_OPCODE_DO_BIND, 0));
 
11574                 address += sizeof(pint_t);
 
11576         mid.push_back(binding_tmp(BIND_OPCODE_DONE, 0));
 
11579         // optimize phase 1, combine bind/add pairs
 
11580         binding_tmp* dst = &mid[0];
 
11581         for (const binding_tmp* src = &mid[0]; src->opcode != BIND_OPCODE_DONE; ++src) {
 
11582                 if ( (src->opcode == BIND_OPCODE_DO_BIND) 
 
11583                                 && (src[1].opcode == BIND_OPCODE_ADD_ADDR_ULEB) ) {
 
11584                         dst->opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB;
 
11585                         dst->operand1 = src[1].operand1;
 
11593         dst->opcode = BIND_OPCODE_DONE;
 
11595         // optimize phase 2, compress packed runs of BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB with
 
11596         // same addr delta into one BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
 
11598         for (const binding_tmp* src = &mid[0]; src->opcode != BIND_OPCODE_DONE; ++src) {
 
11599                 uint64_t delta = src->operand1;
 
11600                 if ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB) 
 
11601                                 && (src[1].opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB) 
 
11602                                 && (src[1].operand1 == delta) ) {
 
11603                         // found at least two in a row, this is worth compressing
 
11604                         dst->opcode = BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB;
 
11606                         dst->operand2 = delta;
 
11608                         while ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
 
11609                                         && (src->operand1 == delta) ) {
 
11620         dst->opcode = BIND_OPCODE_DONE;
 
11622         // optimize phase 3, use immediate encodings
 
11623         for (binding_tmp* p = &mid[0]; p->opcode != REBASE_OPCODE_DONE; ++p) {
 
11624                 if ( (p->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB) 
 
11625                         && (p->operand1 < (15*sizeof(pint_t)))
 
11626                         && ((p->operand1 % sizeof(pint_t)) == 0) ) {
 
11627                         p->opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED;
 
11628                         p->operand1 = p->operand1/sizeof(pint_t);
 
11630                 else if ( (p->opcode == BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB) && (p->operand1 <= 15) ) {
 
11631                         p->opcode = BIND_OPCODE_SET_DYLIB_ORDINAL_IMM;
 
11634         dst->opcode = BIND_OPCODE_DONE;
 
11636         // convert to compressed encoding
 
11637         const static bool log = false;
 
11638         fEncodedData.reserve(info.size()*2);
 
11640         for (std::vector<binding_tmp>::iterator it = mid.begin(); !done && it != mid.end() ; ++it) {
 
11641                 switch ( it->opcode ) {
 
11642                         case BIND_OPCODE_DONE:
 
11643                                 if ( log ) fprintf(stderr, "BIND_OPCODE_DONE()\n");
 
11646                         case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
 
11647                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM(%lld)\n", it->operand1);
 
11648                                 fEncodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | it->operand1);
 
11650                         case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
 
11651                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB(%lld)\n", it->operand1);
 
11652                                 fEncodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
 
11653                                 fEncodedData.append_uleb128(it->operand1);
 
11655                         case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
 
11656                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM(%lld)\n", it->operand1);
 
11657                                 fEncodedData.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | (it->operand1 & BIND_IMMEDIATE_MASK));
 
11659                         case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
 
11660                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM(0x%0llX, %s)\n", it->operand1, it->name);
 
11661                                 fEncodedData.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | it->operand1);
 
11662                                 fEncodedData.append_string(it->name);
 
11664                         case BIND_OPCODE_SET_TYPE_IMM:
 
11665                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_TYPE_IMM(%lld)\n", it->operand1);
 
11666                                 fEncodedData.append_byte(BIND_OPCODE_SET_TYPE_IMM | it->operand1);
 
11668                         case BIND_OPCODE_SET_ADDEND_SLEB:
 
11669                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_ADDEND_SLEB(%lld)\n", it->operand1);
 
11670                                 fEncodedData.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
 
11671                                 fEncodedData.append_sleb128(it->operand1);
 
11673                         case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
 
11674                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(%lld, 0x%llX)\n", it->operand1, it->operand2);
 
11675                                 fEncodedData.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | it->operand1);
 
11676                                 fEncodedData.append_uleb128(it->operand2);
 
11678                         case BIND_OPCODE_ADD_ADDR_ULEB:
 
11679                                 if ( log ) fprintf(stderr, "BIND_OPCODE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
 
11680                                 fEncodedData.append_byte(BIND_OPCODE_ADD_ADDR_ULEB);
 
11681                                 fEncodedData.append_uleb128(it->operand1);
 
11683                         case BIND_OPCODE_DO_BIND:
 
11684                                 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND()\n");
 
11685                                 fEncodedData.append_byte(BIND_OPCODE_DO_BIND);
 
11687                         case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
 
11688                                 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
 
11689                                 fEncodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB);
 
11690                                 fEncodedData.append_uleb128(it->operand1);
 
11692                         case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
 
11693                                 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED(%lld=0x%llX)\n", it->operand1, it->operand1*sizeof(pint_t));
 
11694                                 fEncodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED | it->operand1 );
 
11696                         case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
 
11697                                 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB(%lld, %lld)\n", it->operand1, it->operand2);
 
11698                                 fEncodedData.append_byte(BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);
 
11699                                 fEncodedData.append_uleb128(it->operand1);
 
11700                                 fEncodedData.append_uleb128(it->operand2);
 
11705         // align to pointer size
 
11706         fEncodedData.pad_to_size(sizeof(pint_t));
 
11708         if (log) fprintf(stderr, "total binding info size = %ld\n", fEncodedData.size());
 
11714 struct WeakBindingSorter
 
11716      bool operator()(const BindingInfo& left, const BindingInfo& right)
 
11718                 // sort by symbol, type, address
 
11719                 if ( left.fSymbolName != right.fSymbolName )
 
11720                         return ( strcmp(left.fSymbolName, right.fSymbolName) < 0 );
 
11721                 if ( left.fType != right.fType )
 
11722                         return  (left.fType < right.fType);
 
11723                 return  (left.fAddress < right.fAddress);
 
11729 template <typename A>
 
11730 void CompressedWeakBindingInfoLinkEditAtom<A>::encode()
 
11732         // add regular atoms that override a dylib's weak definitions 
 
11733         for(std::set<const class ObjectFile::Atom*>::iterator it = fWriter.fRegularDefAtomsThatOverrideADylibsWeakDef->begin();
 
11734                                                                                                         it != fWriter.fRegularDefAtomsThatOverrideADylibsWeakDef->end(); ++it) {
 
11735                 if ( fWriter.shouldExport(**it) )
 
11736                         fWriter.fWeakBindingInfo.push_back(BindingInfo(0, (*it)->getName(), true, 0, 0));
 
11739         // add all exported weak definitions
 
11740         for(std::vector<class ObjectFile::Atom*>::iterator it = fWriter.fAllAtoms->begin(); it != fWriter.fAllAtoms->end(); ++it) {
 
11741                 ObjectFile::Atom* atom = *it;
 
11742                 if ( (atom->getDefinitionKind() == ObjectFile::Atom::kWeakDefinition) && fWriter.shouldExport(*atom) ) {
 
11743                         fWriter.fWeakBindingInfo.push_back(BindingInfo(0, atom->getName(), false, 0, 0));
 
11747         // sort by symbol, type, address
 
11748         const std::vector<SegmentInfo*>& segments = fWriter.fSegmentInfos;
 
11749         std::vector<BindingInfo>& info = fWriter.fWeakBindingInfo;
 
11750         if ( info.size() == 0 )
 
11752         std::sort(info.begin(), info.end(), WeakBindingSorter());
 
11754         // convert to temp encoding that can be more easily optimized
 
11755         std::vector<binding_tmp> mid;
 
11756         mid.reserve(info.size());
 
11757         const SegmentInfo* currentSegment = NULL;
 
11758         unsigned int segIndex = 0;
 
11759         const char* symbolName = NULL;
 
11761         uint64_t address = (uint64_t)(-1);
 
11762         int64_t addend = 0;
 
11763         for (std::vector<BindingInfo>::iterator it = info.begin(); it != info.end(); ++it) {
 
11764                 if ( symbolName != it->fSymbolName ) {
 
11765                         mid.push_back(binding_tmp(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM, it->fFlags, 0, it->fSymbolName));
 
11766                         symbolName = it->fSymbolName;
 
11768                 if ( it->fType != 0 ) {
 
11769                         if ( type != it->fType ) {
 
11770                                 mid.push_back(binding_tmp(BIND_OPCODE_SET_TYPE_IMM, it->fType));
 
11773                         if ( address != it->fAddress ) {
 
11774                                 // non weak symbols just have BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
 
11775                                 // weak symbols have SET_SEG, ADD_ADDR, SET_ADDED, DO_BIND
 
11776                                 if ( (currentSegment == NULL) || (it->fAddress < currentSegment->fBaseAddress) 
 
11777                                                 || ((currentSegment->fBaseAddress+currentSegment->fSize) <=it->fAddress) ) {
 
11779                                         for (std::vector<SegmentInfo*>::const_iterator segit = segments.begin(); segit != segments.end(); ++segit) {
 
11780                                                 if ( ((*segit)->fBaseAddress <= it->fAddress) && (it->fAddress < ((*segit)->fBaseAddress+(*segit)->fSize)) ) {
 
11781                                                         currentSegment = *segit;
 
11786                                         mid.push_back(binding_tmp(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, segIndex, it->fAddress - currentSegment->fBaseAddress));
 
11789                                         mid.push_back(binding_tmp(BIND_OPCODE_ADD_ADDR_ULEB, it->fAddress-address));
 
11791                                 address = it->fAddress;
 
11793                         if ( addend != it->fAddend ) {
 
11794                                 mid.push_back(binding_tmp(BIND_OPCODE_SET_ADDEND_SLEB, it->fAddend));
 
11795                                 addend = it->fAddend;
 
11797                         mid.push_back(binding_tmp(BIND_OPCODE_DO_BIND, 0));
 
11798                         address += sizeof(pint_t);
 
11801         mid.push_back(binding_tmp(BIND_OPCODE_DONE, 0));
 
11804         // optimize phase 1, combine bind/add pairs
 
11805         binding_tmp* dst = &mid[0];
 
11806         for (const binding_tmp* src = &mid[0]; src->opcode != BIND_OPCODE_DONE; ++src) {
 
11807                 if ( (src->opcode == BIND_OPCODE_DO_BIND) 
 
11808                                 && (src[1].opcode == BIND_OPCODE_ADD_ADDR_ULEB) ) {
 
11809                         dst->opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB;
 
11810                         dst->operand1 = src[1].operand1;
 
11818         dst->opcode = BIND_OPCODE_DONE;
 
11820         // optimize phase 2, compress packed runs of BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB with
 
11821         // same addr delta into one BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
 
11823         for (const binding_tmp* src = &mid[0]; src->opcode != BIND_OPCODE_DONE; ++src) {
 
11824                 uint64_t delta = src->operand1;
 
11825                 if ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB) 
 
11826                                 && (src[1].opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB) 
 
11827                                 && (src[1].operand1 == delta) ) {
 
11828                         // found at least two in a row, this is worth compressing
 
11829                         dst->opcode = BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB;
 
11831                         dst->operand2 = delta;
 
11833                         while ( (src->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB)
 
11834                                         && (src->operand1 == delta) ) {
 
11845         dst->opcode = BIND_OPCODE_DONE;
 
11847         // optimize phase 3, use immediate encodings
 
11848         for (binding_tmp* p = &mid[0]; p->opcode != REBASE_OPCODE_DONE; ++p) {
 
11849                 if ( (p->opcode == BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB) 
 
11850                         && (p->operand1 < (15*sizeof(pint_t)))
 
11851                         && ((p->operand1 % sizeof(pint_t)) == 0) ) {
 
11852                         p->opcode = BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED;
 
11853                         p->operand1 = p->operand1/sizeof(pint_t);
 
11856         dst->opcode = BIND_OPCODE_DONE;
 
11859         // convert to compressed encoding
 
11860         const static bool log = false;
 
11861         fEncodedData.reserve(info.size()*2);
 
11863         for (std::vector<binding_tmp>::iterator it = mid.begin(); !done && it != mid.end() ; ++it) {
 
11864                 switch ( it->opcode ) {
 
11865                         case BIND_OPCODE_DONE:
 
11866                                 if ( log ) fprintf(stderr, "BIND_OPCODE_DONE()\n");
 
11867                                 fEncodedData.append_byte(BIND_OPCODE_DONE);
 
11870                         case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
 
11871                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM(%lld)\n", it->operand1);
 
11872                                 fEncodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | it->operand1);
 
11874                         case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
 
11875                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB(%lld)\n", it->operand1);
 
11876                                 fEncodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
 
11877                                 fEncodedData.append_uleb128(it->operand1);
 
11879                         case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
 
11880                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM(%lld)\n", it->operand1);
 
11881                                 fEncodedData.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | (it->operand1 & BIND_IMMEDIATE_MASK));
 
11883                         case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
 
11884                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM(0x%0llX, %s)\n", it->operand1, it->name);
 
11885                                 fEncodedData.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | it->operand1);
 
11886                                 fEncodedData.append_string(it->name);
 
11888                         case BIND_OPCODE_SET_TYPE_IMM:
 
11889                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_TYPE_IMM(%lld)\n", it->operand1);
 
11890                                 fEncodedData.append_byte(BIND_OPCODE_SET_TYPE_IMM | it->operand1);
 
11892                         case BIND_OPCODE_SET_ADDEND_SLEB:
 
11893                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_ADDEND_SLEB(%lld)\n", it->operand1);
 
11894                                 fEncodedData.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
 
11895                                 fEncodedData.append_sleb128(it->operand1);
 
11897                         case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
 
11898                                 if ( log ) fprintf(stderr, "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(%lld, 0x%llX)\n", it->operand1, it->operand2);
 
11899                                 fEncodedData.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | it->operand1);
 
11900                                 fEncodedData.append_uleb128(it->operand2);
 
11902                         case BIND_OPCODE_ADD_ADDR_ULEB:
 
11903                                 if ( log ) fprintf(stderr, "BIND_OPCODE_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
 
11904                                 fEncodedData.append_byte(BIND_OPCODE_ADD_ADDR_ULEB);
 
11905                                 fEncodedData.append_uleb128(it->operand1);
 
11907                         case BIND_OPCODE_DO_BIND:
 
11908                                 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND()\n");
 
11909                                 fEncodedData.append_byte(BIND_OPCODE_DO_BIND);
 
11911                         case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
 
11912                                 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB(0x%llX)\n", it->operand1);
 
11913                                 fEncodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB);
 
11914                                 fEncodedData.append_uleb128(it->operand1);
 
11916                         case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
 
11917                                 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED(%lld=0x%llX)\n", it->operand1, it->operand1*sizeof(pint_t));
 
11918                                 fEncodedData.append_byte(BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED | it->operand1 );
 
11920                         case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
 
11921                                 if ( log ) fprintf(stderr, "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB(%lld, %lld)\n", it->operand1, it->operand2);
 
11922                                 fEncodedData.append_byte(BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);
 
11923                                 fEncodedData.append_uleb128(it->operand1);
 
11924                                 fEncodedData.append_uleb128(it->operand2);
 
11929         // align to pointer size
 
11930         fEncodedData.pad_to_size(sizeof(pint_t));
 
11932         if (log) fprintf(stderr, "total weak binding info size = %ld\n", fEncodedData.size());
 
11936 template <typename A>
 
11937 void CompressedLazyBindingInfoLinkEditAtom<A>::encode()
 
11939         // stream all lazy bindings and record start offsets
 
11940         const SegmentInfo* currentSegment = NULL;
 
11941         uint8_t segIndex = 0;
 
11942         const std::vector<SegmentInfo*>& segments = fWriter.fSegmentInfos;
 
11943         std::vector<class LazyPointerAtom<A>*>& allLazys = fWriter.fAllSynthesizedLazyPointers;
 
11944         for (typename std::vector<class LazyPointerAtom<A>*>::iterator it = allLazys.begin(); it != allLazys.end(); ++it) {
 
11945                 LazyPointerAtom<A>* lazyPointerAtom = *it;
 
11946                 ObjectFile::Atom* lazyPointerTargetAtom = lazyPointerAtom->getTarget();
 
11948                 // skip lazy pointers that are bound non-lazily because they are coalesced
 
11949                 if ( ! fWriter.targetRequiresWeakBinding(*lazyPointerTargetAtom) ) {                    
 
11950                         // record start offset for use by stub helper
 
11951                         lazyPointerAtom->setLazyBindingInfoOffset(fEncodedData.size());
 
11953                         // write address to bind
 
11954                         pint_t address = lazyPointerAtom->getAddress();
 
11955                         if ( (currentSegment == NULL) || (address < currentSegment->fBaseAddress) 
 
11956                                         || ((currentSegment->fBaseAddress+currentSegment->fSize) <= address) ) {
 
11958                                 for (std::vector<SegmentInfo*>::const_iterator segit = segments.begin(); segit != segments.end(); ++segit) {
 
11959                                         if ( ((*segit)->fBaseAddress <= address) && (address < ((*segit)->fBaseAddress+(*segit)->fSize)) ) {
 
11960                                                 currentSegment = *segit;
 
11966                         fEncodedData.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | segIndex);
 
11967                         fEncodedData.append_uleb128(lazyPointerAtom->getAddress() - currentSegment->fBaseAddress);
 
11970                         int ordinal = fWriter.compressedOrdinalForImortedAtom(lazyPointerTargetAtom);
 
11971                         if ( ordinal <= 0 ) {
 
11972                                 // special lookups are encoded as negative numbers in BindingInfo
 
11973                                 fEncodedData.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | (ordinal & BIND_IMMEDIATE_MASK) );
 
11975                         else if ( ordinal <= 15 ) {
 
11976                                 // small ordinals are encoded in opcode
 
11977                                 fEncodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | ordinal);
 
11980                                 fEncodedData.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
 
11981                                 fEncodedData.append_uleb128(ordinal);
 
11983                         // write symbol name
 
11984                         bool weak_import = fWriter.fWeakImportMap[lazyPointerTargetAtom];
 
11986                                 fEncodedData.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | BIND_SYMBOL_FLAGS_WEAK_IMPORT);
 
11988                                 fEncodedData.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
 
11989                         fEncodedData.append_string(lazyPointerTargetAtom->getName());
 
11991                         fEncodedData.append_byte(BIND_OPCODE_DO_BIND);
 
11992                         fEncodedData.append_byte(BIND_OPCODE_DONE);
 
11995         // align to pointer size
 
11996         fEncodedData.pad_to_size(sizeof(pint_t));
 
11998         //fprintf(stderr, "lazy binding info size = %ld, for %ld entries\n", fEncodedData.size(), allLazys.size());
 
12001 struct TrieEntriesSorter
 
12003         TrieEntriesSorter(Options& o) : fOptions(o) {}
 
12005      bool operator()(const mach_o::trie::Entry& left, const mach_o::trie::Entry& right)
 
12007                 unsigned int leftOrder;
 
12008                 unsigned int rightOrder;
 
12009                 fOptions.exportedSymbolOrder(left.name, &leftOrder);
 
12010                 fOptions.exportedSymbolOrder(right.name, &rightOrder);
 
12011                 if ( leftOrder != rightOrder ) 
 
12012                         return (leftOrder < rightOrder);
 
12014                         return (left.address < right.address);
 
12021 template <typename A>
 
12022 void CompressedExportInfoLinkEditAtom<A>::encode()
 
12024         // make vector of mach_o::trie::Entry for all exported symbols
 
12025         std::vector<class ObjectFile::Atom*>& exports = fWriter.fExportedAtoms;
 
12026         uint64_t imageBaseAddress = fWriter.fMachHeaderAtom->getAddress();
 
12027         std::vector<mach_o::trie::Entry> entries;
 
12028         entries.reserve(exports.size());
 
12029         for (std::vector<ObjectFile::Atom*>::iterator it = exports.begin(); it != exports.end(); ++it) {
 
12030                 ObjectFile::Atom* atom = *it;
 
12031                 uint64_t flags = 0;
 
12032                 if ( atom->getDefinitionKind() == ObjectFile::Atom::kWeakDefinition )
 
12033                         flags |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
 
12034                 uint64_t address = atom->getAddress() - imageBaseAddress;
 
12035                 if ( atom->isThumb() )
 
12037                 mach_o::trie::Entry entry;
 
12038                 entry.name = atom->getName();
 
12039                 entry.flags = flags;
 
12040                 entry.address = address; 
 
12041                 entries.push_back(entry);
 
12044         // sort vector by -exported_symbols_order, and any others by address
 
12045         std::sort(entries.begin(), entries.end(), TrieEntriesSorter(fWriter.fOptions));
 
12048         mach_o::trie::makeTrie(entries, fEncodedData.bytes());
 
12050         // align to pointer size
 
12051         fEncodedData.pad_to_size(sizeof(pint_t));
 
12058 }; // namespace executable
 
12059 }; // namespace mach_o
 
12062 #endif // __EXECUTABLE_MACH_O__