1 /* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
 
   3  * Copyright (c) 2005-2007 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 <mach-o/loader.h>
 
  33 #include <mach-o/nlist.h>
 
  34 #include <mach-o/reloc.h>
 
  35 //#include <mach-o/ppc/reloc.h>
 
  36 #include <mach-o/stab.h>
 
  37 #include <uuid/uuid.h>
 
  38 #include <mach/i386/thread_status.h>
 
  39 #include <mach/ppc/thread_status.h>
 
  40 #include <CommonCrypto/CommonDigest.h>
 
  46 #include <ext/hash_map>
 
  48 #include "ObjectFile.h"
 
  49 #include "ExecutableFile.h"
 
  52 #include "MachOFileAbstraction.hpp"
 
  55   #define S_DTRACE_DOF 0xF
 
  59         #define MH_PIE 0x200000 
 
  64 //      To implement architecture xxx, you must write template specializations for the following methods:
 
  65 //                      MachHeaderAtom<xxx>::setHeaderInfo()
 
  66 //                      ThreadsLoadCommandsAtom<xxx>::getSize()
 
  67 //                      ThreadsLoadCommandsAtom<xxx>::copyRawContent()
 
  68 //                      Writer<xxx>::addObjectRelocs()
 
  69 //                      Writer<xxx>::fixUpReferenceRelocatable()
 
  70 //                      Writer<xxx>::fixUpReferenceFinal()
 
  71 //                      Writer<xxx>::stubableReference()
 
  72 //                      Writer<xxx>::weakImportReferenceKind()
 
  73 //                      Writer<xxx>::GOTReferenceKind()
 
  78 namespace executable {
 
  81 template <typename A> class WriterAtom;
 
  82 template <typename A> class PageZeroAtom;
 
  83 template <typename A> class CustomStackAtom;
 
  84 template <typename A> class MachHeaderAtom;
 
  85 template <typename A> class SegmentLoadCommandsAtom;
 
  86 template <typename A> class SymbolTableLoadCommandsAtom;
 
  87 template <typename A> class ThreadsLoadCommandsAtom;
 
  88 template <typename A> class DylibIDLoadCommandsAtom;
 
  89 template <typename A> class RoutinesLoadCommandsAtom;
 
  90 template <typename A> class DyldLoadCommandsAtom;
 
  91 template <typename A> class UUIDLoadCommandAtom;
 
  92 template <typename A> class LinkEditAtom;
 
  93 template <typename A> class SectionRelocationsLinkEditAtom;
 
  94 template <typename A> class LocalRelocationsLinkEditAtom;
 
  95 template <typename A> class ExternalRelocationsLinkEditAtom;
 
  96 template <typename A> class SymbolTableLinkEditAtom;
 
  97 template <typename A> class SegmentSplitInfoLoadCommandsAtom;
 
  98 template <typename A> class SegmentSplitInfoContentAtom;
 
  99 template <typename A> class IndirectTableLinkEditAtom;
 
 100 template <typename A> class ModuleInfoLinkEditAtom;
 
 101 template <typename A> class StringsLinkEditAtom;
 
 102 template <typename A> class LoadCommandsPaddingAtom;
 
 103 template <typename A> class StubAtom;
 
 104 template <typename A> class StubHelperAtom;
 
 105 template <typename A> class LazyPointerAtom;
 
 106 template <typename A> class NonLazyPointerAtom;
 
 107 template <typename A> class DylibLoadCommandsAtom;
 
 110 // SectionInfo should be nested inside Writer, but I can't figure out how to make the type accessible to the Atom classes
 
 111 class SectionInfo : public ObjectFile::Section {
 
 113                                                                                 SectionInfo() : fFileOffset(0), fSize(0), fRelocCount(0), fRelocOffset(0), fIndirectSymbolOffset(0),
 
 114                                                                                                                 fAlignment(0), fAllLazyPointers(false), fAllNonLazyPointers(false), fAllStubs(false),
 
 115                                                                                                                 fAllSelfModifyingStubs(false), fAllZeroFill(false), fVirtualSection(false)
 
 116                                                                                                                 { fSegmentName[0] = '\0'; fSectionName[0] = '\0'; }
 
 117         void                                                            setIndex(unsigned int index) { fIndex=index; }
 
 118         std::vector<ObjectFile::Atom*>          fAtoms;
 
 119         char                                                            fSegmentName[20];
 
 120         char                                                            fSectionName[20];
 
 121         uint64_t                                                        fFileOffset;
 
 123         uint32_t                                                        fRelocCount;
 
 124         uint32_t                                                        fRelocOffset;
 
 125         uint32_t                                                        fIndirectSymbolOffset;
 
 127         bool                                                            fAllLazyPointers;
 
 128         bool                                                            fAllNonLazyPointers;
 
 130         bool                                                            fAllSelfModifyingStubs;
 
 132         bool                                                            fVirtualSection;
 
 135 // SegmentInfo should be nested inside Writer, but I can't figure out how to make the type accessible to the Atom classes
 
 139                                                                                 SegmentInfo() : fInitProtection(0), fMaxProtection(0), fFileOffset(0), fFileSize(0),
 
 140                                                                                                                 fBaseAddress(0), fSize(0), fFixedAddress(false), 
 
 141                                                                                                                 fIndependentAddress(false) { fName[0] = '\0'; }
 
 142         std::vector<class SectionInfo*>         fSections;
 
 144         uint32_t                                                        fInitProtection;
 
 145         uint32_t                                                        fMaxProtection;
 
 146         uint64_t                                                        fFileOffset;
 
 148         uint64_t                                                        fBaseAddress;
 
 151         bool                                                            fIndependentAddress;
 
 154 template <typename A>
 
 155 class Writer : public ExecutableFile::Writer
 
 158         Writer(const char* path, Options& options, std::vector<ExecutableFile::DyLibUsed>& dynamicLibraries);
 
 161         virtual const char*                                                             getPath()                                                               { return fFilePath; }
 
 162         virtual time_t                                                                  getModificationTime()                                   { return 0; }
 
 163         virtual DebugInfoKind                                                   getDebugInfoKind()                                              { return ObjectFile::Reader::kDebugInfoNone; }
 
 164         virtual std::vector<class ObjectFile::Atom*>&   getAtoms()                                                              { return fWriterSynthesizedAtoms; }
 
 165         virtual std::vector<class ObjectFile::Atom*>*   getJustInTimeAtomsFor(const char* name) { return NULL; }
 
 166         virtual std::vector<Stab>*                                              getStabs()                                                              { return NULL; }
 
 168         virtual ObjectFile::Atom&                                               makeObjcInfoAtom(ObjectFile::Reader::ObjcConstraint objcContraint, 
 
 169                                                                                                                                                 bool objcReplacementClasses);
 
 170         virtual class ObjectFile::Atom*                                 getUndefinedProxyAtom(const char* name);
 
 171         virtual uint64_t                                                                write(std::vector<class ObjectFile::Atom*>& atoms,
 
 172                                                                                                                   std::vector<class ObjectFile::Reader::Stab>& stabs,
 
 173                                                                                                                   class ObjectFile::Atom* entryPointAtom,
 
 174                                                                                                                   class ObjectFile::Atom* dyldHelperAtom,
 
 175                                                                                                                   bool createUUID, bool canScatter,
 
 176                                                                                                                   ObjectFile::Reader::CpuConstraint cpuConstraint,
 
 177                                                                                                                   bool biggerThanTwoGigs);
 
 180         typedef typename A::P                   P;
 
 181         typedef typename A::P::uint_t   pint_t;
 
 183         enum RelocKind { kRelocNone, kRelocInternal, kRelocExternal };
 
 185         void                                            assignFileOffsets();
 
 186         void                                            synthesizeStubs();
 
 187         void                                            insertDummyStubs();
 
 188         void                                            partitionIntoSections();
 
 189         bool                                            addBranchIslands();
 
 190         bool                                            addPPCBranchIslands();
 
 191         bool                                            isBranch24Reference(uint8_t kind);
 
 192         void                                            adjustLoadCommandsAndPadding();
 
 193         void                                            createDynamicLinkerCommand();
 
 194         void                                            createDylibCommands();
 
 195         void                                            buildLinkEdit();
 
 196         const char*                                     getArchString();
 
 198         uint64_t                                        writeAtoms();
 
 199         void                                            writeNoOps(uint32_t from, uint32_t to);
 
 200         void                                            copyNoOps(uint8_t* from, uint8_t* to);
 
 201         bool                                            segmentsCanSplitApart(const ObjectFile::Atom& from, const ObjectFile::Atom& to);
 
 202         void                                            addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref);
 
 203         void                                            collectExportedAndImportedAndLocalAtoms();
 
 204         void                                            setNlistRange(std::vector<class ObjectFile::Atom*>& atoms, uint32_t startIndex, uint32_t count);
 
 205         void                                            addLocalLabel(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* name);
 
 206         void                                            addGlobalLabel(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* name);
 
 207         void                                            buildSymbolTable();
 
 208         const char*                                     symbolTableName(const ObjectFile::Atom* atom);
 
 209         void                                            setExportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry);
 
 210         void                                            setImportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry);
 
 211         void                                            setLocalNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry);
 
 212         void                                            copyNlistRange(const std::vector<macho_nlist<P> >& entries, uint32_t startIndex);
 
 213         uint64_t                                        getAtomLoadAddress(const ObjectFile::Atom* atom);
 
 214         uint8_t                                         ordinalForLibrary(ObjectFile::Reader* file);
 
 215         bool                                            shouldExport(const ObjectFile::Atom& atom) const;
 
 217         void                                            adjustLinkEditSections();
 
 218         void                                            buildObjectFileFixups();
 
 219         void                                            buildExecutableFixups();
 
 220         bool                                            preboundLazyPointerType(uint8_t* type);
 
 221         uint64_t                                        relocAddressInFinalLinkedImage(uint64_t address, const ObjectFile::Atom* atom) const;
 
 222         void                                            fixUpReferenceFinal(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const;
 
 223         void                                            fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const;
 
 224         void                                            fixUpReference_powerpc(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom,
 
 225                                                                                                                 uint8_t buffer[], bool finalLinkedImage) const;
 
 226         uint32_t                                        symbolIndex(ObjectFile::Atom& atom);
 
 227         bool                                            makesExternalRelocatableReference(ObjectFile::Atom& target) const;
 
 228         uint32_t                                        addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref);
 
 229         uint32_t                                        addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::Reference* ref);
 
 230         uint8_t                                         getRelocPointerSize();
 
 231         uint64_t                                        maxAddress();
 
 232         bool                                            stubableReference(const ObjectFile::Reference* ref);
 
 233         bool                                            GOTReferenceKind(uint8_t kind);
 
 234         bool                                            optimizableGOTReferenceKind(uint8_t kind);
 
 235         bool                                            weakImportReferenceKind(uint8_t kind);
 
 236         unsigned int                            collectStabs();
 
 237         uint64_t                                        valueForStab(const ObjectFile::Reader::Stab& stab);
 
 238         uint32_t                                        stringOffsetForStab(const ObjectFile::Reader::Stab& stab);
 
 239         uint8_t                                         sectionIndexForStab(const ObjectFile::Reader::Stab& stab);
 
 240         void                                            addStabs(uint32_t startIndex);
 
 241         RelocKind                                       relocationNeededInFinalLinkedImage(const ObjectFile::Atom& target) const;
 
 242         bool                                            illegalRelocInFinalLinkedImage(const ObjectFile::Reference&);
 
 243         bool                                            mightNeedPadSegment();
 
 244         void                                            scanForAbsoluteReferences();
 
 245         bool                                            needsModuleTable();
 
 246         void                                            optimizeDylibReferences();
 
 247         bool                                            indirectSymbolIsLocal(const ObjectFile::Reference* ref) const;
 
 249         struct DirectLibrary {
 
 250                 class ObjectFile::Reader*       fLibrary;
 
 255         friend class WriterAtom<A>;
 
 256         friend class PageZeroAtom<A>;
 
 257         friend class CustomStackAtom<A>;
 
 258         friend class MachHeaderAtom<A>;
 
 259         friend class SegmentLoadCommandsAtom<A>;
 
 260         friend class SymbolTableLoadCommandsAtom<A>;
 
 261         friend class ThreadsLoadCommandsAtom<A>;
 
 262         friend class DylibIDLoadCommandsAtom<A>;
 
 263         friend class RoutinesLoadCommandsAtom<A>;
 
 264         friend class DyldLoadCommandsAtom<A>;
 
 265         friend class UUIDLoadCommandAtom<A>;
 
 266         friend class LinkEditAtom<A>;
 
 267         friend class SectionRelocationsLinkEditAtom<A>;
 
 268         friend class LocalRelocationsLinkEditAtom<A>;
 
 269         friend class ExternalRelocationsLinkEditAtom<A>;
 
 270         friend class SymbolTableLinkEditAtom<A>;
 
 271         friend class SegmentSplitInfoLoadCommandsAtom<A>;
 
 272         friend class SegmentSplitInfoContentAtom<A>;
 
 273 //      friend class IndirectTableLinkEditAtom<A>;
 
 274         friend class ModuleInfoLinkEditAtom<A>;
 
 275         friend class StringsLinkEditAtom<A>;
 
 276         friend class LoadCommandsPaddingAtom<A>;
 
 277         friend class StubAtom<A>;
 
 278         friend class StubHelperAtom<A>;
 
 279         friend class LazyPointerAtom<A>;
 
 280         friend class NonLazyPointerAtom<A>;
 
 281         friend class DylibLoadCommandsAtom<A>;
 
 283         const char*                                                                             fFilePath;
 
 286         std::vector<class ObjectFile::Atom*>*                   fAllAtoms;
 
 287         std::vector<class ObjectFile::Reader::Stab>*    fStabs;
 
 288         class SectionInfo*                                                              fLoadCommandsSection;
 
 289         class SegmentInfo*                                                              fLoadCommandsSegment;
 
 290         class SegmentLoadCommandsAtom<A>*                               fSegmentCommands;
 
 291         class SymbolTableLoadCommandsAtom<A>*                   fSymbolTableCommands;
 
 292         class LoadCommandsPaddingAtom<A>*                               fHeaderPadding;
 
 293         class UUIDLoadCommandAtom<A>*                               fUUIDAtom;
 
 294         std::vector<class ObjectFile::Atom*>                    fWriterSynthesizedAtoms;
 
 295         std::vector<SegmentInfo*>                                               fSegmentInfos;
 
 296         class SegmentInfo*                                                              fPadSegmentInfo;
 
 297         class ObjectFile::Atom*                                                 fEntryPoint;
 
 298         class ObjectFile::Atom*                                                 fDyldHelper;
 
 299         std::map<class ObjectFile::Reader*, DylibLoadCommandsAtom<A>*>  fLibraryToLoadCommand;
 
 300         std::map<class ObjectFile::Reader*, uint32_t>   fLibraryToOrdinal;
 
 301         std::map<class ObjectFile::Reader*, class ObjectFile::Reader*>  fLibraryAliases;
 
 302         std::vector<class ObjectFile::Atom*>                    fExportedAtoms;
 
 303         std::vector<class ObjectFile::Atom*>                    fImportedAtoms;
 
 304         std::vector<class ObjectFile::Atom*>                    fLocalSymbolAtoms;
 
 305         std::vector<macho_nlist<P> >                                    fLocalExtraLabels;
 
 306         std::vector<macho_nlist<P> >                                    fGlobalExtraLabels;
 
 307         class SectionRelocationsLinkEditAtom<A>*                fSectionRelocationsAtom;
 
 308         class LocalRelocationsLinkEditAtom<A>*                  fLocalRelocationsAtom;
 
 309         class ExternalRelocationsLinkEditAtom<A>*               fExternalRelocationsAtom;
 
 310         class SymbolTableLinkEditAtom<A>*                               fSymbolTableAtom;
 
 311         class SegmentSplitInfoContentAtom<A>*                   fSplitCodeToDataContentAtom;
 
 312         class IndirectTableLinkEditAtom<A>*                             fIndirectTableAtom;
 
 313         class ModuleInfoLinkEditAtom<A>*                                fModuleInfoAtom;
 
 314         class StringsLinkEditAtom<A>*                                   fStringsAtom;
 
 315         class PageZeroAtom<A>*                                                  fPageZeroAtom;
 
 316         macho_nlist<P>*                                                                 fSymbolTable;
 
 317         std::vector<macho_relocation_info<P> >                  fSectionRelocs;
 
 318         std::vector<macho_relocation_info<P> >                  fInternalRelocs;
 
 319         std::vector<macho_relocation_info<P> >                  fExternalRelocs;
 
 320         std::map<const ObjectFile::Atom*,ObjectFile::Atom*>     fStubsMap;
 
 321         std::map<ObjectFile::Atom*,ObjectFile::Atom*>   fGOTMap;
 
 322         std::vector<class StubAtom<A>*>                                 fAllSynthesizedStubs;
 
 323         std::vector<ObjectFile::Atom*>                                  fAllSynthesizedStubHelpers;
 
 324         std::vector<class LazyPointerAtom<A>*>                  fAllSynthesizedLazyPointers;
 
 325         std::vector<class NonLazyPointerAtom<A>*>               fAllSynthesizedNonLazyPointers;
 
 326         uint32_t                                                                                fSymbolTableCount;
 
 327         uint32_t                                                                                fSymbolTableStabsCount;
 
 328         uint32_t                                                                                fSymbolTableStabsStartIndex;
 
 329         uint32_t                                                                                fSymbolTableLocalCount;
 
 330         uint32_t                                                                                fSymbolTableLocalStartIndex;
 
 331         uint32_t                                                                                fSymbolTableExportCount;
 
 332         uint32_t                                                                                fSymbolTableExportStartIndex;
 
 333         uint32_t                                                                                fSymbolTableImportCount;
 
 334         uint32_t                                                                                fSymbolTableImportStartIndex;
 
 335         uint32_t                                                                                fLargestAtomSize;
 
 336         bool                                                                                    fEmitVirtualSections;
 
 337         bool                                                                                    fHasWeakExports;
 
 338         bool                                                                                    fReferencesWeakImports;
 
 340         bool                                                                                    fWritableSegmentPastFirst4GB;
 
 341         bool                                                                                    fNoReExportedDylibs;
 
 342         bool                                                                                    fBiggerThanTwoGigs;
 
 344         std::map<const ObjectFile::Atom*,bool>                  fWeakImportMap;
 
 345         SegmentInfo*                                                                    fFirstWritableSegment;
 
 346         ObjectFile::Reader::CpuConstraint                               fCpuConstraint;
 
 347         uint32_t                                                                                fAnonNameIndex;
 
 351 class Segment : public ObjectFile::Segment
 
 354                                                                 Segment(const char* name, bool readable, bool writable, bool executable, bool fixedAddress)
 
 355                                                                                          : fName(name), fReadable(readable), fWritable(writable), fExecutable(executable), fFixedAddress(fixedAddress) {}
 
 356         virtual const char*                     getName() const                                 { return fName; }
 
 357         virtual bool                            isContentReadable() const               { return fReadable; }
 
 358         virtual bool                            isContentWritable() const               { return fWritable; }
 
 359         virtual bool                            isContentExecutable() const             { return fExecutable; }
 
 360         virtual bool                            hasFixedAddress() const                 { return fFixedAddress; }
 
 362         static Segment                                                          fgTextSegment;
 
 363         static Segment                                                          fgPageZeroSegment;
 
 364         static Segment                                                          fgLinkEditSegment;
 
 365         static Segment                                                          fgStackSegment;
 
 366         static Segment                                                          fgImportSegment;
 
 367         static Segment                                                          fgROImportSegment;
 
 368         static Segment                                                          fgDataSegment;
 
 369         static Segment                                                          fgObjCSegment;
 
 374         const bool                                      fReadable;
 
 375         const bool                                      fWritable;
 
 376         const bool                                      fExecutable;
 
 377         const bool                                      fFixedAddress;
 
 380 Segment         Segment::fgPageZeroSegment("__PAGEZERO", false, false, false, true);
 
 381 Segment         Segment::fgTextSegment("__TEXT", true, false, true, false);
 
 382 Segment         Segment::fgLinkEditSegment("__LINKEDIT", true, false, false, false);
 
 383 Segment         Segment::fgStackSegment("__UNIXSTACK", true, true, false, true);
 
 384 Segment         Segment::fgImportSegment("__IMPORT", true, true, true, false);
 
 385 Segment         Segment::fgROImportSegment("__IMPORT", true, false, true, false);
 
 386 Segment         Segment::fgDataSegment("__DATA", true, true, false, false);
 
 387 Segment         Segment::fgObjCSegment("__OBJC", true, true, false, false);
 
 390 template <typename A>
 
 391 class WriterAtom : public ObjectFile::Atom
 
 394         enum Kind { zeropage, machHeaderApp, machHeaderDylib, machHeaderBundle, machHeaderObject, loadCommands, undefinedProxy };
 
 395                                                                                         WriterAtom(Writer<A>& writer, Segment& segment) : fWriter(writer), fSegment(segment) { }
 
 397         virtual ObjectFile::Reader*                             getFile() const                                 { return &fWriter; }
 
 398         virtual bool                                                    getTranslationUnitSource(const char** dir, const char** name) const { return false; }
 
 399         virtual const char*                                             getName() const                                 { return NULL; }
 
 400         virtual const char*                                             getDisplayName() const                  { return this->getName(); }
 
 401         virtual Scope                                                   getScope() const                                { return ObjectFile::Atom::scopeTranslationUnit; }
 
 402         virtual DefinitionKind                                  getDefinitionKind() const               { return kRegularDefinition; }
 
 403         virtual SymbolTableInclusion                    getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableNotIn; }
 
 404         virtual bool                                                    dontDeadStrip() const                   { return true; }
 
 405         virtual bool                                                    isZeroFill() const                              { return false; }
 
 406         virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return fgEmptyReferenceList; }
 
 407         virtual bool                                                    mustRemainInSection() const             { return true; }
 
 408         virtual ObjectFile::Segment&                    getSegment() const                              { return fSegment; }
 
 409         virtual ObjectFile::Atom&                               getFollowOnAtom() const                 { return *((ObjectFile::Atom*)NULL); }
 
 410         virtual uint32_t                                                getOrdinal() const                              { return 0; }
 
 411         virtual std::vector<ObjectFile::LineInfo>*      getLineInfo() const                     { return NULL; }
 
 412         virtual ObjectFile::Alignment                   getAlignment() const                    { return ObjectFile::Alignment(2); }
 
 413         virtual void                                                    copyRawContent(uint8_t buffer[]) const { throw "don't use copyRawContent"; }
 
 414         virtual void                                                    setScope(Scope)                                 { }
 
 418         virtual                                                                 ~WriterAtom() {}
 
 419         typedef typename A::P                                   P;
 
 420         typedef typename A::P::E                                E;
 
 422         static std::vector<ObjectFile::Reference*>      fgEmptyReferenceList;
 
 428 template <typename A> std::vector<ObjectFile::Reference*>       WriterAtom<A>::fgEmptyReferenceList;
 
 431 template <typename A>
 
 432 class PageZeroAtom : public WriterAtom<A>
 
 435                                                                                         PageZeroAtom(Writer<A>& writer) : WriterAtom<A>(writer, Segment::fgPageZeroSegment),
 
 436                                                                                                                                                         fSize(fWriter.fOptions.zeroPageSize()) {}
 
 437         virtual const char*                                             getDisplayName() const  { return "page zero content"; }
 
 438         virtual bool                                                    isZeroFill() const              { return true; }
 
 439         virtual uint64_t                                                getSize() const                 { return fSize; }
 
 440         virtual const char*                                             getSectionName() const  { return "._zeropage"; }
 
 441         virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(12); }
 
 442         void                                                                    setSize(uint64_t size)  { fSize = size; }
 
 444         using WriterAtom<A>::fWriter;
 
 445         typedef typename A::P                                   P;
 
 450 template <typename A>
 
 451 class DsoHandleAtom : public WriterAtom<A>
 
 454                                                                                                         DsoHandleAtom(Writer<A>& writer) : WriterAtom<A>(writer, Segment::fgTextSegment) {}
 
 455         virtual const char*                                                             getName() const                         { return "___dso_handle"; }
 
 456         virtual ObjectFile::Atom::Scope                                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
 
 457         virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableNotIn; }
 
 458         virtual uint64_t                                                                getSize() const                         { return 0; }
 
 459         virtual ObjectFile::Alignment                                   getAlignment() const            { return ObjectFile::Alignment(12); }
 
 460         virtual const char*                                                             getSectionName() const          { return "._mach_header"; }
 
 461         virtual void                                                                    copyRawContent(uint8_t buffer[]) const {}
 
 465 template <typename A>
 
 466 class MachHeaderAtom : public WriterAtom<A>
 
 469                                                                                                         MachHeaderAtom(Writer<A>& writer) : WriterAtom<A>(writer, Segment::fgTextSegment) {}
 
 470         virtual const char*                                                             getName() const;
 
 471         virtual const char*                                                             getDisplayName() const;
 
 472         virtual ObjectFile::Atom::Scope                                 getScope() const;
 
 473         virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const;
 
 474         virtual uint64_t                                                                getSize() const                         { return sizeof(macho_header<typename A::P>); }
 
 475         virtual ObjectFile::Alignment                                   getAlignment() const            { return ObjectFile::Alignment(12); }
 
 476         virtual const char*                                                             getSectionName() const          { return "._mach_header"; }
 
 477         virtual uint32_t                                                                getOrdinal() const                      { return 1; }
 
 478         virtual void                                                                    copyRawContent(uint8_t buffer[]) const;
 
 480         using WriterAtom<A>::fWriter;
 
 481         typedef typename A::P                                   P;
 
 482         void                                                                    setHeaderInfo(macho_header<typename A::P>& header) const;
 
 485 template <typename A>
 
 486 class CustomStackAtom : public WriterAtom<A>
 
 489                                                                                         CustomStackAtom(Writer<A>& writer);
 
 490         virtual const char*                                             getDisplayName() const  { return "custom stack content"; }
 
 491         virtual bool                                                    isZeroFill() const              { return true; }
 
 492         virtual uint64_t                                                getSize() const                 { return fWriter.fOptions.customStackSize(); }
 
 493         virtual const char*                                             getSectionName() const  { return "._stack"; }
 
 494         virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(12); }
 
 496         using WriterAtom<A>::fWriter;
 
 497         typedef typename A::P                                   P;
 
 498         static bool                                                             stackGrowsDown();
 
 501 template <typename A>
 
 502 class LoadCommandAtom : public WriterAtom<A>
 
 505                                                                                         LoadCommandAtom(Writer<A>& writer, Segment& segment) : WriterAtom<A>(writer, segment), fOrdinal(fgCurrentOrdinal++) {}
 
 506         virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(log2(sizeof(typename A::P::uint_t))); }
 
 507         virtual const char*                                             getSectionName() const  { return "._load_commands"; }
 
 508         virtual uint32_t                                                getOrdinal() const              { return fOrdinal; }
 
 509         static uint64_t                                                 alignedSize(uint64_t size);
 
 512         static uint32_t                                                 fgCurrentOrdinal;
 
 515 template <typename A> uint32_t LoadCommandAtom<A>::fgCurrentOrdinal = 0;
 
 517 template <typename A>
 
 518 class SegmentLoadCommandsAtom : public LoadCommandAtom<A>
 
 521                                                                                         SegmentLoadCommandsAtom(Writer<A>& writer)  
 
 522                                                                                                 : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fCommandCount(0), fSize(0) 
 
 523                                                                                                 { writer.fSegmentCommands = this; }
 
 524         virtual const char*                                             getDisplayName() const  { return "segment load commands"; }
 
 525         virtual uint64_t                                                getSize() const                 { return fSize; }
 
 526         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 530         unsigned int                                                    commandCount()                  { return fCommandCount; }
 
 532         using WriterAtom<A>::fWriter;
 
 533         typedef typename A::P                                   P;
 
 534         unsigned int                                                    fCommandCount;
 
 539 template <typename A>
 
 540 class SymbolTableLoadCommandsAtom : public LoadCommandAtom<A>
 
 543                                                                                         SymbolTableLoadCommandsAtom(Writer<A>&);
 
 544         virtual const char*                                             getDisplayName() const { return "symbol table load commands"; }
 
 545         virtual uint64_t                                                getSize() const;
 
 546         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 547         unsigned int                                                    commandCount();
 
 548                         void                                                    needDynamicTable();
 
 550         using WriterAtom<A>::fWriter;
 
 551         typedef typename A::P                                   P;
 
 552         bool                                                                    fNeedsDynamicSymbolTable;
 
 553         macho_symtab_command<typename A::P>             fSymbolTable;
 
 554         macho_dysymtab_command<typename A::P>   fDynamicSymbolTable;
 
 557 template <typename A>
 
 558 class ThreadsLoadCommandsAtom : public LoadCommandAtom<A>
 
 561                                                                                         ThreadsLoadCommandsAtom(Writer<A>& writer) 
 
 562                                                                                                 : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
 
 563         virtual const char*                                             getDisplayName() const { return "thread load commands"; }
 
 564         virtual uint64_t                                                getSize() const;
 
 565         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 567         using WriterAtom<A>::fWriter;
 
 568         typedef typename A::P                                   P;
 
 570         uint32_t                                                                fBufferSize;
 
 573 template <typename A>
 
 574 class DyldLoadCommandsAtom : public LoadCommandAtom<A>
 
 577                                                                                         DyldLoadCommandsAtom(Writer<A>& writer)  : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
 
 578         virtual const char*                                             getDisplayName() const  { return "dyld load command"; }
 
 579         virtual uint64_t                                                getSize() const;
 
 580         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 582         using WriterAtom<A>::fWriter;
 
 583         typedef typename A::P                                   P;
 
 586 template <typename A>
 
 587 class SegmentSplitInfoLoadCommandsAtom : public LoadCommandAtom<A>
 
 590                                                                                         SegmentSplitInfoLoadCommandsAtom(Writer<A>& writer)  : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
 
 591         virtual const char*                                             getDisplayName() const  { return "segment split info load command"; }
 
 592         virtual uint64_t                                                getSize() const;
 
 593         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 595         using WriterAtom<A>::fWriter;
 
 596         typedef typename A::P                                   P;
 
 599 template <typename A>
 
 600 class AllowableClientLoadCommandsAtom : public LoadCommandAtom<A>
 
 603         AllowableClientLoadCommandsAtom(Writer<A>& writer, const char* client)  :
 
 604                 LoadCommandAtom<A>(writer, Segment::fgTextSegment), clientString(client) {}
 
 605         virtual const char*                                                     getDisplayName() const  { return "allowable_client load command"; }
 
 606         virtual uint64_t                                                        getSize() const;
 
 607         virtual void                                                            copyRawContent(uint8_t buffer[]) const;
 
 609         using WriterAtom<A>::fWriter;
 
 610         typedef typename A::P                                           P;
 
 611         const char*                                                                     clientString;
 
 614 template <typename A>
 
 615 class DylibLoadCommandsAtom : public LoadCommandAtom<A>
 
 618                                                                                         DylibLoadCommandsAtom(Writer<A>& writer, ExecutableFile::DyLibUsed& info) 
 
 619                                                                                          : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fInfo(info), fOptimizedAway(false) {}
 
 620         virtual const char*                                             getDisplayName() const  { return "dylib load command"; }
 
 621         virtual uint64_t                                                getSize() const;
 
 622         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 623         virtual void                                                    optimizeAway() { fOptimizedAway = true; }
 
 625         using WriterAtom<A>::fWriter;
 
 626         typedef typename A::P                                   P;
 
 627         ExecutableFile::DyLibUsed                               fInfo;
 
 631 template <typename A>
 
 632 class DylibIDLoadCommandsAtom : public LoadCommandAtom<A>
 
 635                                                                                         DylibIDLoadCommandsAtom(Writer<A>& writer) : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
 
 636         virtual const char*                                             getDisplayName() const { return "dylib ID load command"; }
 
 637         virtual uint64_t                                                getSize() const;
 
 638         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 640         using WriterAtom<A>::fWriter;
 
 641         typedef typename A::P                                   P;
 
 644 template <typename A>
 
 645 class RoutinesLoadCommandsAtom : public LoadCommandAtom<A>
 
 648                                                                                         RoutinesLoadCommandsAtom(Writer<A>& writer) : LoadCommandAtom<A>(writer, Segment::fgTextSegment) {}
 
 649         virtual const char*                                             getDisplayName() const { return "routines load command"; }
 
 650         virtual uint64_t                                                getSize() const                 { return sizeof(macho_routines_command<typename A::P>); }
 
 651         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 653         using WriterAtom<A>::fWriter;
 
 654         typedef typename A::P                                   P;
 
 657 template <typename A>
 
 658 class SubUmbrellaLoadCommandsAtom : public LoadCommandAtom<A>
 
 661                                                                                         SubUmbrellaLoadCommandsAtom(Writer<A>& writer, const char* name) 
 
 662                                                                                          : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fName(name) {}
 
 663         virtual const char*                                             getDisplayName() const  { return "sub-umbrella load command"; }
 
 664         virtual uint64_t                                                getSize() const;
 
 665         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 667         typedef typename A::P                                   P;
 
 671 template <typename A>
 
 672 class SubLibraryLoadCommandsAtom : public LoadCommandAtom<A>
 
 675                                                                                         SubLibraryLoadCommandsAtom(Writer<A>& writer,  const char* nameStart, int nameLen)
 
 676                                                                                                 : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fNameStart(nameStart), fNameLength(nameLen) {}
 
 677         virtual const char*                                             getDisplayName() const  { return "sub-library load command"; }
 
 678         virtual uint64_t                                                getSize() const;
 
 679         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 681         using WriterAtom<A>::fWriter;
 
 682         typedef typename A::P                                   P;
 
 683         const char*                                                             fNameStart;
 
 687 template <typename A>
 
 688 class UmbrellaLoadCommandsAtom : public LoadCommandAtom<A>
 
 691                                                                                         UmbrellaLoadCommandsAtom(Writer<A>& writer, const char* name)
 
 692                                                                                                         : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fName(name) {}
 
 693         virtual const char*                                             getDisplayName() const  { return "umbrella load command"; }
 
 694         virtual uint64_t                                                getSize() const;
 
 695         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 697         using WriterAtom<A>::fWriter;
 
 698         typedef typename A::P                                   P;
 
 702 template <typename A>
 
 703 class UUIDLoadCommandAtom : public LoadCommandAtom<A>
 
 706                                                                                         UUIDLoadCommandAtom(Writer<A>& writer)
 
 707                                                                                                 : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fEmit(false) {}
 
 708         virtual const char*                                             getDisplayName() const  { return "uuid load command"; }
 
 709         virtual uint64_t                                                getSize() const                 { return fEmit ? sizeof(macho_uuid_command<typename A::P>) : 0; }
 
 710         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 711         virtual void                                                generate();
 
 712                         void                                                setContent(const uint8_t uuid[16]);
 
 713                         const uint8_t*                                  getUUID()                               { return fUUID; }
 
 715         using WriterAtom<A>::fWriter;
 
 716         typedef typename A::P                                   P;
 
 722 template <typename A>
 
 723 class RPathLoadCommandsAtom : public LoadCommandAtom<A>
 
 726                                                                                         RPathLoadCommandsAtom(Writer<A>& writer, const char* path)
 
 727                                                                                                 : LoadCommandAtom<A>(writer, Segment::fgTextSegment), fPath(path) {}
 
 728         virtual const char*                                             getDisplayName() const  { return "rpath load command"; }
 
 729         virtual uint64_t                                                getSize() const;
 
 730         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 732         using WriterAtom<A>::fWriter;
 
 733         typedef typename A::P                                   P;
 
 738 template <typename A>
 
 739 class LoadCommandsPaddingAtom : public WriterAtom<A>
 
 742                                                                                         LoadCommandsPaddingAtom(Writer<A>& writer)
 
 743                                                                                                         : WriterAtom<A>(writer, Segment::fgTextSegment), fSize(0) {}
 
 744         virtual const char*                                             getDisplayName() const  { return "header padding"; }
 
 745         virtual uint64_t                                                getSize() const                 { return fSize; }
 
 746         virtual const char*                                             getSectionName() const  { return "._load_cmds_pad"; }
 
 747         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 749         void                                                                    setSize(uint64_t newSize);
 
 751         using WriterAtom<A>::fWriter;
 
 752         typedef typename A::P                                   P;
 
 756 template <typename A>
 
 757 class LinkEditAtom : public WriterAtom<A>
 
 760                                                                                         LinkEditAtom(Writer<A>& writer) : WriterAtom<A>(writer, Segment::fgLinkEditSegment), fOrdinal(fgCurrentOrdinal++) {}
 
 761         uint64_t                                                                getFileOffset() const;
 
 762         virtual ObjectFile::Alignment                   getAlignment() const    { return ObjectFile::Alignment(log2(sizeof(typename A::P::uint_t))); }
 
 763         virtual uint32_t                                                getOrdinal() const              { return fOrdinal; }
 
 766         static uint32_t                                                 fgCurrentOrdinal;
 
 768         typedef typename A::P                                   P;
 
 771 template <typename A> uint32_t LinkEditAtom<A>::fgCurrentOrdinal = 0;
 
 773 template <typename A>
 
 774 class SectionRelocationsLinkEditAtom : public LinkEditAtom<A>
 
 777                                                                                         SectionRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
 
 778         virtual const char*                                             getDisplayName() const  { return "section relocations"; }
 
 779         virtual uint64_t                                                getSize() const;
 
 780         virtual const char*                                             getSectionName() const  { return "._section_relocs"; }
 
 781         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 783         using WriterAtom<A>::fWriter;
 
 784         typedef typename A::P                                   P;
 
 787 template <typename A>
 
 788 class LocalRelocationsLinkEditAtom : public LinkEditAtom<A>
 
 791                                                                                         LocalRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
 
 792         virtual const char*                                             getDisplayName() const  { return "local relocations"; }
 
 793         virtual uint64_t                                                getSize() const;
 
 794         virtual const char*                                             getSectionName() const  { return "._local_relocs"; }
 
 795         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 797         using WriterAtom<A>::fWriter;
 
 798         typedef typename A::P                                   P;
 
 801 template <typename A>
 
 802 class SymbolTableLinkEditAtom : public LinkEditAtom<A>
 
 805                                                                                         SymbolTableLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
 
 806         virtual const char*                                             getDisplayName() const  { return "symbol table"; }
 
 807         virtual uint64_t                                                getSize() const;
 
 808         virtual const char*                                             getSectionName() const  { return "._symbol_table"; }
 
 809         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 811         using WriterAtom<A>::fWriter;
 
 812         typedef typename A::P                                   P;
 
 815 template <typename A>
 
 816 class ExternalRelocationsLinkEditAtom : public LinkEditAtom<A>
 
 819                                                                                         ExternalRelocationsLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
 
 820         virtual const char*                                             getDisplayName() const  { return "external relocations"; }
 
 821         virtual uint64_t                                                getSize() const;
 
 822         virtual const char*                                             getSectionName() const  { return "._extern_relocs"; }
 
 823         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 825         using WriterAtom<A>::fWriter;
 
 826         typedef typename A::P                                   P;
 
 829 struct IndirectEntry {
 
 830         uint32_t        indirectIndex;
 
 831         uint32_t        symbolIndex;
 
 835 template <typename A>
 
 836 class SegmentSplitInfoContentAtom : public LinkEditAtom<A>
 
 839                                                                                         SegmentSplitInfoContentAtom(Writer<A>& writer) : LinkEditAtom<A>(writer), fCantEncode(false) { }
 
 840         virtual const char*                                             getDisplayName() const  { return "split segment info"; }
 
 841         virtual uint64_t                                                getSize() const;
 
 842         virtual const char*                                             getSectionName() const  { return "._split_info"; }
 
 843         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 844         bool                                                                    canEncode()                                             { return !fCantEncode; }
 
 845         void                                                                    setCantEncode()                                 { fCantEncode = true; }
 
 846         void                                                                    add32bitPointerLocation(const ObjectFile::Atom* atom, uint32_t offset) { fKind1Locations.push_back(AtomAndOffset(atom, offset)); }
 
 847         void                                                                    add64bitPointerLocation(const ObjectFile::Atom* atom, uint32_t offset) { fKind2Locations.push_back(AtomAndOffset(atom, offset)); }
 
 848         void                                                                    addPPCHi16Location(const ObjectFile::Atom* atom, uint32_t offset) { fKind3Locations.push_back(AtomAndOffset(atom, offset)); }
 
 849         void                                                                    add32bitImportLocation(const ObjectFile::Atom* atom, uint32_t offset) { fKind4Locations.push_back(AtomAndOffset(atom, offset)); }
 
 853         using WriterAtom<A>::fWriter;
 
 854         typedef typename A::P                                   P;
 
 855         typedef typename A::P::uint_t                   pint_t;
 
 856         struct AtomAndOffset { 
 
 857                         AtomAndOffset(const ObjectFile::Atom* a, uint32_t off) : atom(a), offset(off) {}
 
 858                         const ObjectFile::Atom*         atom; 
 
 861         void                                                                    uleb128EncodeAddresses(const std::vector<AtomAndOffset>& locations);
 
 863         std::vector<AtomAndOffset>                              fKind1Locations;
 
 864         std::vector<AtomAndOffset>                              fKind2Locations;
 
 865         std::vector<AtomAndOffset>                              fKind3Locations;
 
 866         std::vector<AtomAndOffset>                              fKind4Locations;
 
 867         std::vector<uint8_t>                                    fEncodedData;
 
 871 template <typename A>
 
 872 class IndirectTableLinkEditAtom : public LinkEditAtom<A>
 
 875                                                                                         IndirectTableLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer) { }
 
 876         virtual const char*                                             getDisplayName() const  { return "indirect symbol table"; }
 
 877         virtual uint64_t                                                getSize() const;
 
 878         virtual const char*                                             getSectionName() const  { return "._indirect_syms"; }
 
 879         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 881         std::vector<IndirectEntry>                              fTable;
 
 884         using WriterAtom<A>::fWriter;
 
 885         typedef typename A::P                                   P;
 
 888 template <typename A>
 
 889 class ModuleInfoLinkEditAtom : public LinkEditAtom<A>
 
 892                                                                                         ModuleInfoLinkEditAtom(Writer<A>& writer) : LinkEditAtom<A>(writer), fModuleNameOffset(0) { }
 
 893         virtual const char*                                             getDisplayName() const  { return "modulel table"; }
 
 894         virtual uint64_t                                                getSize() const;
 
 895         virtual const char*                                             getSectionName() const  { return "._module_info"; }
 
 896         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 898                         void                                                    setName() { fModuleNameOffset = fWriter.fStringsAtom->add("single module"); }
 
 899                         uint32_t                                                getTableOfContentsFileOffset() const;
 
 900                         uint32_t                                                getModuleTableFileOffset() const;
 
 901                         uint32_t                                                getReferencesFileOffset() const;
 
 902                         uint32_t                                                getReferencesCount() const;
 
 905         using WriterAtom<A>::fWriter;
 
 906         typedef typename A::P                                   P;
 
 907         uint32_t                                                                fModuleNameOffset;
 
 914         bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
 
 917 template <typename A>
 
 918 class StringsLinkEditAtom : public LinkEditAtom<A>
 
 921                                                                                         StringsLinkEditAtom(Writer<A>& writer);
 
 922         virtual const char*                                             getDisplayName() const  { return "string pool"; }
 
 923         virtual uint64_t                                                getSize() const;
 
 924         virtual const char*                                             getSectionName() const  { return "._string_pool"; }
 
 925         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 927         int32_t                                                                 add(const char* name);
 
 928         int32_t                                                                 addUnique(const char* name);
 
 929         int32_t                                                                 emptyString()                   { return 1; }
 
 930         const char*                                                             stringForIndex(int32_t) const;
 
 933         using WriterAtom<A>::fWriter;
 
 934         typedef typename A::P                                   P;
 
 935         enum { kBufferSize = 0x01000000 };
 
 936         typedef __gnu_cxx::hash_map<const char*, int32_t, __gnu_cxx::hash<const char*>, CStringEquals> StringToOffset;
 
 938         std::vector<char*>                                              fFullBuffers;
 
 939         char*                                                                   fCurrentBuffer;
 
 940         uint32_t                                                                fCurrentBufferUsed;
 
 941         StringToOffset                                                  fUniqueStrings;
 
 946 template <typename A>
 
 947 class UndefinedSymbolProxyAtom : public WriterAtom<A>
 
 950                                                                                                         UndefinedSymbolProxyAtom(Writer<A>& writer, const char* name) : WriterAtom<A>(writer, Segment::fgLinkEditSegment), fName(name) {}
 
 951         virtual const char*                                                             getName() const                         { return fName; }
 
 952         virtual ObjectFile::Atom::Scope                                 getScope() const                        { return ObjectFile::Atom::scopeGlobal; }
 
 953         virtual ObjectFile::Atom::DefinitionKind                getDefinitionKind() const       { return ObjectFile::Atom::kExternalDefinition; }
 
 954         virtual ObjectFile::Atom::SymbolTableInclusion  getSymbolTableInclusion() const { return ObjectFile::Atom::kSymbolTableIn; }
 
 955         virtual uint64_t                                                                getSize() const                         { return 0; }
 
 956         virtual const char*                                                             getSectionName() const          { return "._imports"; }
 
 958         using WriterAtom<A>::fWriter;
 
 959         typedef typename A::P                                   P;
 
 963 template <typename A>
 
 964 class BranchIslandAtom : public WriterAtom<A>
 
 967                                                                                         BranchIslandAtom(Writer<A>& writer, const char* name, int islandRegion, ObjectFile::Atom& target, uint32_t targetOffset);
 
 968         virtual const char*                                             getName() const                         { return fName; }
 
 969         virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
 
 970         virtual uint64_t                                                getSize() const;
 
 971         virtual const char*                                             getSectionName() const          { return "__text"; }
 
 972         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 974         using WriterAtom<A>::fWriter;
 
 976         ObjectFile::Atom&                                               fTarget;
 
 977         uint32_t                                                                fTargetOffset;
 
 980 template <typename A>
 
 981 class StubAtom : public WriterAtom<A>
 
 984                                                                                         StubAtom(Writer<A>& writer, ObjectFile::Atom& target);
 
 985         virtual const char*                                             getName() const                         { return fName; }
 
 986         virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
 
 987         virtual uint64_t                                                getSize() const;
 
 988         virtual ObjectFile::Alignment                   getAlignment() const;
 
 989         virtual const char*                                             getSectionName() const          { return "__symbol_stub1"; }
 
 990         virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
 
 991         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
 992         ObjectFile::Atom*                                               getTarget()                                     { return &fTarget; }
 
 994         static const char*                                              stubName(const char* importName);
 
 996         using WriterAtom<A>::fWriter;
 
 998         ObjectFile::Atom&                                               fTarget;
 
 999         std::vector<ObjectFile::Reference*>             fReferences;
 
1002 template <typename A>
 
1003 class StubHelperAtom : public WriterAtom<A>
 
1006                                                                                         StubHelperAtom(Writer<A>& writer, ObjectFile::Atom& target, ObjectFile::Atom& lazyPointer);
 
1007         virtual const char*                                             getName() const                         { return fName; }
 
1008         virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
 
1009         virtual uint64_t                                                getSize() const;
 
1010         virtual const char*                                             getSectionName() const          { return "__stub_helper"; }
 
1011         virtual std::vector<ObjectFile::Reference*>&  getReferences() const     { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
 
1012         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1013         ObjectFile::Atom*                                               getTarget()                                     { return &fTarget; }
 
1015         static const char*                                              stubName(const char* importName);
 
1016         using WriterAtom<A>::fWriter;
 
1018         ObjectFile::Atom&                                               fTarget;
 
1019         std::vector<ObjectFile::Reference*>             fReferences;
 
1022 template <typename A>
 
1023 class LazyPointerAtom : public WriterAtom<A>
 
1026                                                                                         LazyPointerAtom(Writer<A>& writer, ObjectFile::Atom& target);
 
1027         virtual const char*                                             getName() const                         { return fName; }
 
1028         virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
 
1029         virtual uint64_t                                                getSize() const                         { return sizeof(typename A::P::uint_t); }
 
1030         virtual const char*                                             getSectionName() const          { return "__la_symbol_ptr"; }
 
1031         virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
 
1032         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1033         ObjectFile::Atom*                                               getTarget()                                     { return &fTarget; }
 
1035         using WriterAtom<A>::fWriter;
 
1036         static const char*                                              lazyPointerName(const char* importName);
 
1038         ObjectFile::Atom&                                               fTarget;
 
1039         std::vector<ObjectFile::Reference*>             fReferences;
 
1043 template <typename A>
 
1044 class NonLazyPointerAtom : public WriterAtom<A>
 
1047                                                                                         NonLazyPointerAtom(Writer<A>& writer, ObjectFile::Atom& target);
 
1048         virtual const char*                                             getName() const                         { return fName; }
 
1049         virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
 
1050         virtual uint64_t                                                getSize() const                         { return sizeof(typename A::P::uint_t); }
 
1051         virtual const char*                                             getSectionName() const          { return "__nl_symbol_ptr"; }
 
1052         virtual std::vector<ObjectFile::Reference*>&  getReferences() const             { return (std::vector<ObjectFile::Reference*>&)(fReferences); }
 
1053         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1054         ObjectFile::Atom*                                               getTarget()                                     { return &fTarget; }
 
1056         using WriterAtom<A>::fWriter;
 
1057         static const char*                                              nonlazyPointerName(const char* importName);
 
1059         ObjectFile::Atom&                                               fTarget;
 
1060         std::vector<ObjectFile::Reference*>             fReferences;
 
1064 template <typename A>
 
1065 class ObjCInfoAtom : public WriterAtom<A>
 
1068                                                                                         ObjCInfoAtom(Writer<A>& writer, ObjectFile::Reader::ObjcConstraint objcContraint,
 
1069                                                                                                                 bool objcReplacementClasses);
 
1070         virtual const char*                                             getName() const                         { return "objc$info"; }
 
1071         virtual ObjectFile::Atom::Scope                 getScope() const                        { return ObjectFile::Atom::scopeLinkageUnit; }
 
1072         virtual uint64_t                                                getSize() const                         { return 8; }
 
1073         virtual const char*                                             getSectionName() const;
 
1074         virtual void                                                    copyRawContent(uint8_t buffer[]) const;
 
1076         Segment&                                                                getInfoSegment() const;
 
1077         uint32_t                                                                fContent[2];
 
1081 template <typename A>
 
1082 class WriterReference : public ObjectFile::Reference
 
1085         typedef typename A::ReferenceKinds                      Kinds;
 
1087                                                         WriterReference(uint32_t offset, Kinds kind, ObjectFile::Atom* target,
 
1088                                                                                         uint32_t toOffset=0, ObjectFile::Atom* fromTarget=NULL, uint32_t fromOffset=0)
 
1089                                                                                   : fKind(kind), fFixUpOffsetInSrc(offset), fTarget(target),
 
1090                                                                                         fTargetOffset(toOffset), fFromTarget(fromTarget), fFromTargetOffset(fromOffset) {}
 
1092         virtual                                 ~WriterReference() {}
 
1094         virtual ObjectFile::Reference::TargetBinding getTargetBinding() const { return ObjectFile::Reference::kBoundDirectly; }
 
1095         virtual ObjectFile::Reference::TargetBinding getFromTargetBinding() const { return (fFromTarget != NULL) ? ObjectFile::Reference::kBoundDirectly : ObjectFile::Reference::kDontBind; }
 
1096         virtual uint8_t                 getKind() const                                                                 { return (uint8_t)fKind; }
 
1097         virtual uint64_t                getFixUpOffset() const                                                  { return fFixUpOffsetInSrc; }
 
1098         virtual const char*             getTargetName() const                                                   { return fTarget->getName(); }
 
1099         virtual ObjectFile::Atom& getTarget() const                                                             { return *fTarget; }
 
1100         virtual uint64_t                getTargetOffset() const                                                 { return fTargetOffset; }
 
1101         virtual ObjectFile::Atom& getFromTarget() const                                                 { return *fFromTarget; }
 
1102         virtual const char*             getFromTargetName() const                                               { return fFromTarget->getName(); }
 
1103         virtual void                    setTarget(ObjectFile::Atom& target, uint64_t offset)    { fTarget = ⌖ fTargetOffset = offset; }
 
1104         virtual void                    setFromTarget(ObjectFile::Atom& target)                 { fFromTarget = ⌖ }
 
1105         virtual void                    setFromTargetName(const char* name)                             {  }
 
1106         virtual void                    setFromTargetOffset(uint64_t offset)                    { fFromTargetOffset = offset; }
 
1107         virtual const char*             getDescription() const                                                  { return "writer reference"; }
 
1108         virtual uint64_t                getFromTargetOffset() const                                             { return fFromTargetOffset; }
 
1112         uint32_t                                fFixUpOffsetInSrc;
 
1113         ObjectFile::Atom*               fTarget;
 
1114         uint32_t                                fTargetOffset;
 
1115         ObjectFile::Atom*               fFromTarget;
 
1116         uint32_t                                fFromTargetOffset;
 
1122 StubHelperAtom<x86_64>::StubHelperAtom(Writer<x86_64>& writer, ObjectFile::Atom& target, ObjectFile::Atom& lazyPointer)
 
1123  : WriterAtom<x86_64>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
 
1125         writer.fAllSynthesizedStubHelpers.push_back(this);
 
1127         fReferences.push_back(new WriterReference<x86_64>(3, x86_64::kPCRel32, &lazyPointer));
 
1128         fReferences.push_back(new WriterReference<x86_64>(8, x86_64::kPCRel32, writer.fDyldHelper));
 
1129         if ( writer.fDyldHelper == NULL )
 
1130                 throw "symbol dyld_stub_binding_helper not defined (usually in crt1.o/dylib1.o/bundle1.o)";
 
1134 uint64_t StubHelperAtom<x86_64>::getSize() const
 
1140 void StubHelperAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
 
1142         buffer[0]  = 0x4C;              // lea foo$lazy_ptr(%rip),%r11
 
1149         buffer[7]  = 0xE9;              // jmp dyld_stub_binding_helper
 
1156 template <typename A>
 
1157 const char* StubHelperAtom<A>::stubName(const char* name)
 
1160         asprintf(&buf, "%s$stubHelper", name);
 
1165 // specialize lazy pointer for x86_64 to initially pointer to stub helper
 
1167 LazyPointerAtom<x86_64>::LazyPointerAtom(Writer<x86_64>& writer, ObjectFile::Atom& target)
 
1168  : WriterAtom<x86_64>(writer, Segment::fgDataSegment), fName(lazyPointerName(target.getName())), fTarget(target)
 
1170         writer.fAllSynthesizedLazyPointers.push_back(this);
 
1172         StubHelperAtom<x86_64>* helper = new StubHelperAtom<x86_64>(writer, target, *this);
 
1173         fReferences.push_back(new WriterReference<x86_64>(0, x86_64::kPointer, helper));
 
1177 template <typename A>
 
1178 LazyPointerAtom<A>::LazyPointerAtom(Writer<A>& writer, ObjectFile::Atom& target)
 
1179  : WriterAtom<A>(writer, Segment::fgDataSegment), fName(lazyPointerName(target.getName())), fTarget(target)
 
1181         writer.fAllSynthesizedLazyPointers.push_back(this);
 
1183         fReferences.push_back(new WriterReference<A>(0, A::kPointer, &target));
 
1188 template <typename A>
 
1189 const char* LazyPointerAtom<A>::lazyPointerName(const char* name)
 
1192         asprintf(&buf, "%s$lazy_pointer", name);
 
1196 template <typename A>
 
1197 void LazyPointerAtom<A>::copyRawContent(uint8_t buffer[]) const
 
1199         bzero(buffer, getSize());
 
1203 template <typename A>
 
1204 NonLazyPointerAtom<A>::NonLazyPointerAtom(Writer<A>& writer, ObjectFile::Atom& target)
 
1205  : WriterAtom<A>(writer, Segment::fgDataSegment), fName(nonlazyPointerName(target.getName())), fTarget(target)
 
1207         writer.fAllSynthesizedNonLazyPointers.push_back(this);
 
1209         fReferences.push_back(new WriterReference<A>(0, A::kPointer, &target));
 
1212 template <typename A>
 
1213 const char* NonLazyPointerAtom<A>::nonlazyPointerName(const char* name)
 
1216         asprintf(&buf, "%s$non_lazy_pointer", name);
 
1220 template <typename A>
 
1221 void NonLazyPointerAtom<A>::copyRawContent(uint8_t buffer[]) const
 
1223         bzero(buffer, getSize());
 
1229 bool StubAtom<ppc64>::pic() const
 
1231         // no-pic stubs for ppc64 don't work if lazy pointer is above low 2GB.
 
1232         // Usually that only happens if page zero is very large
 
1233         return ( fWriter.fSlideable || ((fWriter.fPageZeroAtom != NULL) && (fWriter.fPageZeroAtom->getSize() > 4096)) );
 
1237 bool StubAtom<ppc>::pic() const
 
1239         return fWriter.fSlideable;
 
1243 ObjectFile::Alignment StubAtom<ppc>::getAlignment() const
 
1249 ObjectFile::Alignment StubAtom<ppc64>::getAlignment() const
 
1255 StubAtom<ppc>::StubAtom(Writer<ppc>& writer, ObjectFile::Atom& target)
 
1256  : WriterAtom<ppc>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
 
1258         writer.fAllSynthesizedStubs.push_back(this);
 
1260         LazyPointerAtom<ppc>* lp = new LazyPointerAtom<ppc>(writer, target);
 
1262                 // picbase is 8 bytes into atom
 
1263                 fReferences.push_back(new WriterReference<ppc>(12, ppc::kPICBaseHigh16, lp, 0, this, 8));
 
1264                 fReferences.push_back(new WriterReference<ppc>(20, ppc::kPICBaseLow16, lp, 0, this, 8));
 
1267                 fReferences.push_back(new WriterReference<ppc>(0, ppc::kAbsHigh16AddLow, lp));
 
1268                 fReferences.push_back(new WriterReference<ppc>(4, ppc::kAbsLow16, lp));
 
1273 StubAtom<ppc64>::StubAtom(Writer<ppc64>& writer, ObjectFile::Atom& target)
 
1274  : WriterAtom<ppc64>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
 
1276         writer.fAllSynthesizedStubs.push_back(this);
 
1278         LazyPointerAtom<ppc64>* lp = new LazyPointerAtom<ppc64>(writer, target);
 
1280                 // picbase is 8 bytes into atom
 
1281                 fReferences.push_back(new WriterReference<ppc64>(12, ppc64::kPICBaseHigh16, lp, 0, this, 8));
 
1282                 fReferences.push_back(new WriterReference<ppc64>(20, ppc64::kPICBaseLow14, lp, 0, this, 8));
 
1285                 fReferences.push_back(new WriterReference<ppc64>(0, ppc64::kAbsHigh16AddLow, lp));
 
1286                 fReferences.push_back(new WriterReference<ppc64>(4, ppc64::kAbsLow14, lp));
 
1290 // specialize to put x86 fast stub in __IMPORT segment with no lazy pointer
 
1292 StubAtom<x86>::StubAtom(Writer<x86>& writer, ObjectFile::Atom& target)
 
1293  : WriterAtom<x86>(writer, writer.fOptions.readOnlyx86Stubs() ? Segment::fgROImportSegment : Segment::fgImportSegment), 
 
1296         if ( &target == NULL )
 
1297                 fName = "cache-line-crossing-stub";
 
1299                 fName = stubName(target.getName());
 
1300                 writer.fAllSynthesizedStubs.push_back(this);
 
1305 StubAtom<x86_64>::StubAtom(Writer<x86_64>& writer, ObjectFile::Atom& target)
 
1306  : WriterAtom<x86_64>(writer, Segment::fgTextSegment), fName(stubName(target.getName())), fTarget(target)
 
1308         writer.fAllSynthesizedStubs.push_back(this);
 
1310         LazyPointerAtom<x86_64>* lp = new LazyPointerAtom<x86_64>(writer, target);
 
1311         fReferences.push_back(new WriterReference<x86_64>(2, x86_64::kPCRel32, lp));
 
1314 template <typename A>
 
1315 const char* StubAtom<A>::stubName(const char* name)
 
1318         asprintf(&buf, "%s$stub", name);
 
1323 uint64_t StubAtom<ppc>::getSize() const
 
1325         return ( pic() ? 32 : 16 );
 
1329 uint64_t StubAtom<ppc64>::getSize() const
 
1331         return ( pic() ? 32 : 16 );
 
1335 uint64_t StubAtom<x86>::getSize() const
 
1341 uint64_t StubAtom<x86_64>::getSize() const
 
1347 ObjectFile::Alignment StubAtom<x86>::getAlignment() const
 
1349         // special case x86 fast stubs to be byte aligned
 
1354 void StubAtom<ppc64>::copyRawContent(uint8_t buffer[]) const
 
1357                 OSWriteBigInt32(&buffer [0], 0, 0x7c0802a6);    //      mflr r0
 
1358                 OSWriteBigInt32(&buffer[ 4], 0, 0x429f0005);    //  bcl 20,31,Lpicbase
 
1359                 OSWriteBigInt32(&buffer[ 8], 0, 0x7d6802a6);    // Lpicbase: mflr r11
 
1360                 OSWriteBigInt32(&buffer[12], 0, 0x3d6b0000);    //      addis r11,r11,ha16(L_fwrite$lazy_ptr-Lpicbase)
 
1361                 OSWriteBigInt32(&buffer[16], 0, 0x7c0803a6);    //      mtlr r0
 
1362                 OSWriteBigInt32(&buffer[20], 0, 0xe98b0001);    //      ldu r12,lo16(L_fwrite$lazy_ptr-Lpicbase)(r11)
 
1363                 OSWriteBigInt32(&buffer[24], 0, 0x7d8903a6);    //  mtctr r12
 
1364                 OSWriteBigInt32(&buffer[28], 0, 0x4e800420);    //  bctr
 
1367                 OSWriteBigInt32(&buffer[ 0], 0, 0x3d600000);    // lis r11,ha16(L_fwrite$lazy_ptr)
 
1368                 OSWriteBigInt32(&buffer[ 4], 0, 0xe98b0001);    // ldu r12,lo16(L_fwrite$lazy_ptr)(r11)
 
1369                 OSWriteBigInt32(&buffer[ 8], 0, 0x7d8903a6);    // mtctr r12
 
1370                 OSWriteBigInt32(&buffer[12], 0, 0x4e800420);    // bctr
 
1375 void StubAtom<ppc>::copyRawContent(uint8_t buffer[]) const
 
1378                 OSWriteBigInt32(&buffer[ 0], 0, 0x7c0802a6);    //      mflr r0
 
1379                 OSWriteBigInt32(&buffer[ 4], 0, 0x429f0005);    //  bcl 20,31,Lpicbase
 
1380                 OSWriteBigInt32(&buffer[ 8], 0, 0x7d6802a6);    // Lpicbase: mflr r11
 
1381                 OSWriteBigInt32(&buffer[12], 0, 0x3d6b0000);    //      addis r11,r11,ha16(L_fwrite$lazy_ptr-Lpicbase)
 
1382                 OSWriteBigInt32(&buffer[16], 0, 0x7c0803a6);    //      mtlr r0
 
1383                 OSWriteBigInt32(&buffer[20], 0, 0x858b0000);    //      lwzu r12,lo16(L_fwrite$lazy_ptr-Lpicbase)(r11)
 
1384                 OSWriteBigInt32(&buffer[24], 0, 0x7d8903a6);    //  mtctr r12
 
1385                 OSWriteBigInt32(&buffer[28], 0, 0x4e800420);    //  bctr
 
1388                 OSWriteBigInt32(&buffer[ 0], 0, 0x3d600000);    // lis r11,ha16(L_fwrite$lazy_ptr)
 
1389                 OSWriteBigInt32(&buffer[ 4], 0, 0x858b0000);    // lwzu r12,lo16(L_fwrite$lazy_ptr)(r11)
 
1390                 OSWriteBigInt32(&buffer[ 8], 0, 0x7d8903a6);    // mtctr r12
 
1391                 OSWriteBigInt32(&buffer[12], 0, 0x4e800420);    // bctr
 
1396 void StubAtom<x86>::copyRawContent(uint8_t buffer[]) const
 
1398         if ( fWriter.fOptions.prebind() ) {
 
1399                 uint32_t address = this->getAddress();
 
1400                 int32_t rel32 = 0 - (address+5); 
 
1402                 buffer[1] = rel32 & 0xFF;
 
1403                 buffer[2] = (rel32 >> 8) & 0xFF;
 
1404                 buffer[3] = (rel32 >> 16) & 0xFF;
 
1405                 buffer[4] = (rel32 >> 24) & 0xFF;
 
1417 void StubAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
 
1419         buffer[0] = 0xFF;               // jmp *foo$lazy_pointer(%rip)
 
1427 // x86_64 stubs are 7 bytes and need no alignment
 
1429 ObjectFile::Alignment StubAtom<x86_64>::getAlignment() const
 
1435 const char*     StubAtom<ppc>::getSectionName() const
 
1437         return ( pic() ? "__picsymbolstub1" : "__symbol_stub1");
 
1441 const char*     StubAtom<ppc64>::getSectionName() const
 
1443         return ( pic() ? "__picsymbolstub1" : "__symbol_stub1");
 
1447 const char*     StubAtom<x86>::getSectionName() const
 
1449         return "__jump_table";
 
1455 struct AtomByNameSorter
 
1457      bool operator()(ObjectFile::Atom* left, ObjectFile::Atom* right)
 
1459           return (strcmp(left->getName(), right->getName()) < 0);
 
1463 template <typename P>
 
1464 struct ExternalRelocSorter
 
1466      bool operator()(const macho_relocation_info<P>& left, const macho_relocation_info<P>& right)
 
1468                 // sort first by symbol number
 
1469                 if ( left.r_symbolnum() != right.r_symbolnum() )
 
1470                         return (left.r_symbolnum() < right.r_symbolnum());
 
1471                 // then sort all uses of the same symbol by address
 
1472                 return (left.r_address() < right.r_address());
 
1477 template <typename A>
 
1478 Writer<A>::Writer(const char* path, Options& options, std::vector<ExecutableFile::DyLibUsed>& dynamicLibraries)
 
1479         : ExecutableFile::Writer(dynamicLibraries), fFilePath(strdup(path)), fOptions(options), fLoadCommandsSection(NULL),
 
1480           fLoadCommandsSegment(NULL), fPadSegmentInfo(NULL),  fSplitCodeToDataContentAtom(NULL), fModuleInfoAtom(NULL), 
 
1481           fPageZeroAtom(NULL),  fSymbolTableCount(0),  fLargestAtomSize(1), 
 
1482          fEmitVirtualSections(false), fHasWeakExports(false), fReferencesWeakImports(false), 
 
1483           fCanScatter(false), fWritableSegmentPastFirst4GB(false), fNoReExportedDylibs(false), fSlideable(false), 
 
1484           fFirstWritableSegment(NULL), fAnonNameIndex(1000)
 
1486         // for UNIX conformance, error if file exists and is not writable
 
1487         if ( (access(path, F_OK) == 0) && (access(path, W_OK) == -1) )
 
1488                 throwf("can't write output file: %s", path);
 
1490         int permissions = 0777;
 
1491         if ( fOptions.outputKind() == Options::kObjectFile )
 
1493         // Calling unlink first assures the file is gone so that open creates it with correct permissions
 
1494         // It also handles the case where fFilePath file is not writable but its directory is
 
1495         // And it means we don't have to truncate the file when done writing (in case new is smaller than old)
 
1496         (void)unlink(fFilePath);
 
1497         fFileDescriptor = open(fFilePath, O_CREAT | O_WRONLY | O_TRUNC, permissions);
 
1498         if ( fFileDescriptor == -1 ) {
 
1499                 throwf("can't open output file for writing: %s", path);
 
1502         switch ( fOptions.outputKind() ) {
 
1503                 case Options::kDynamicExecutable:
 
1504                 case Options::kStaticExecutable:
 
1505                         if ( fOptions.zeroPageSize() != 0 )
 
1506                                 fWriterSynthesizedAtoms.push_back(fPageZeroAtom = new PageZeroAtom<A>(*this));
 
1507                         if ( fOptions.outputKind() == Options::kDynamicExecutable )
 
1508                                 fWriterSynthesizedAtoms.push_back(new DsoHandleAtom<A>(*this));
 
1509                         fWriterSynthesizedAtoms.push_back(new MachHeaderAtom<A>(*this));
 
1510                         fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
 
1511                         fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
 
1512                         if ( fOptions.outputKind() == Options::kDynamicExecutable )
 
1513                                 fWriterSynthesizedAtoms.push_back(new DyldLoadCommandsAtom<A>(*this));
 
1514                         fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
 
1515                         fWriterSynthesizedAtoms.push_back(new ThreadsLoadCommandsAtom<A>(*this));
 
1516                         if ( fOptions.hasCustomStack() )
 
1517                                 fWriterSynthesizedAtoms.push_back(new CustomStackAtom<A>(*this));
 
1518                         fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
 
1519                         fWriterSynthesizedAtoms.push_back(fSectionRelocationsAtom = new SectionRelocationsLinkEditAtom<A>(*this));
 
1520                         fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
 
1521                         fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
 
1522                         fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
 
1523                         fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
 
1524                         fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
 
1526                 case Options::kDynamicLibrary:
 
1527                 case Options::kDynamicBundle:
 
1528                         fWriterSynthesizedAtoms.push_back(new DsoHandleAtom<A>(*this));
 
1530                 case Options::kObjectFile:
 
1531                         fWriterSynthesizedAtoms.push_back(new MachHeaderAtom<A>(*this));
 
1532                         fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
 
1533                         if ( fOptions.outputKind() == Options::kDynamicLibrary ) {
 
1534                                 fWriterSynthesizedAtoms.push_back(new DylibIDLoadCommandsAtom<A>(*this));
 
1535                                 if ( fOptions.initFunctionName() != NULL )
 
1536                                         fWriterSynthesizedAtoms.push_back(new RoutinesLoadCommandsAtom<A>(*this));
 
1538                         fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
 
1539                         fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
 
1540                         if ( fOptions.sharedRegionEligible() )
 
1541                                 fWriterSynthesizedAtoms.push_back(new SegmentSplitInfoLoadCommandsAtom<A>(*this));
 
1542                         fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
 
1543                         fWriterSynthesizedAtoms.push_back(fSectionRelocationsAtom = new SectionRelocationsLinkEditAtom<A>(*this));
 
1544                         fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
 
1545                         if ( fOptions.sharedRegionEligible() ) {
 
1546                                 fWriterSynthesizedAtoms.push_back(fSplitCodeToDataContentAtom = new SegmentSplitInfoContentAtom<A>(*this));
 
1548                         fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
 
1549                         fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
 
1550                         fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
 
1551                         if ( this->needsModuleTable() )
 
1552                                 fWriterSynthesizedAtoms.push_back(fModuleInfoAtom = new ModuleInfoLinkEditAtom<A>(*this));
 
1553                         fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
 
1555                 case Options::kDyld:
 
1556                         fWriterSynthesizedAtoms.push_back(new DsoHandleAtom<A>(*this));
 
1557                         fWriterSynthesizedAtoms.push_back(new MachHeaderAtom<A>(*this));
 
1558                         fWriterSynthesizedAtoms.push_back(new SegmentLoadCommandsAtom<A>(*this));
 
1559                         fWriterSynthesizedAtoms.push_back(new SymbolTableLoadCommandsAtom<A>(*this));
 
1560                         fWriterSynthesizedAtoms.push_back(new DyldLoadCommandsAtom<A>(*this));
 
1561                         fWriterSynthesizedAtoms.push_back(fUUIDAtom = new UUIDLoadCommandAtom<A>(*this));
 
1562                         fWriterSynthesizedAtoms.push_back(new ThreadsLoadCommandsAtom<A>(*this));
 
1563                         fWriterSynthesizedAtoms.push_back(fHeaderPadding = new LoadCommandsPaddingAtom<A>(*this));
 
1564                         fWriterSynthesizedAtoms.push_back(fLocalRelocationsAtom = new LocalRelocationsLinkEditAtom<A>(*this));
 
1565                         fWriterSynthesizedAtoms.push_back(fSymbolTableAtom = new SymbolTableLinkEditAtom<A>(*this));
 
1566                         fWriterSynthesizedAtoms.push_back(fExternalRelocationsAtom = new ExternalRelocationsLinkEditAtom<A>(*this));
 
1567                         fWriterSynthesizedAtoms.push_back(fIndirectTableAtom = new IndirectTableLinkEditAtom<A>(*this));
 
1568                         fWriterSynthesizedAtoms.push_back(fStringsAtom = new StringsLinkEditAtom<A>(*this));
 
1572         // add extra commmands
 
1573         bool hasReExports = false;
 
1574         uint8_t ordinal = 1;
 
1575         switch ( fOptions.outputKind() ) {
 
1576                 case Options::kDynamicExecutable:
 
1577                 case Options::kDynamicLibrary:
 
1578                 case Options::kDynamicBundle:
 
1580                                 // add dylib load command atoms for all dynamic libraries
 
1581                                 const unsigned int libCount = dynamicLibraries.size();
 
1582                                 for (unsigned int i=0; i < libCount; ++i) {
 
1583                                         ExecutableFile::DyLibUsed& dylibInfo = dynamicLibraries[i];
 
1584                                         //fprintf(stderr, "dynamicLibraries[%d]: reader=%p, %s, install=%s\n", i, dylibInfo.reader, dylibInfo.reader->getPath(), dylibInfo.reader->getInstallPath() );
 
1586                                         if ( dylibInfo.options.fReExport ) {
 
1587                                                 hasReExports = true;
 
1590                                                 const char* parentUmbrella = dylibInfo.reader->parentUmbrella();
 
1591                                                 if ( (parentUmbrella != NULL) && (fOptions.outputKind() == Options::kDynamicLibrary) ) {
 
1592                                                         const char* thisIDLastSlash = strrchr(fOptions.installPath(), '/');
 
1593                                                         if ( (thisIDLastSlash != NULL) && (strcmp(&thisIDLastSlash[1], parentUmbrella) == 0) )
 
1594                                                                 hasReExports = true;
 
1598                                         if ( dylibInfo.options.fBundleLoader ) {
 
1599                                                 fLibraryToOrdinal[dylibInfo.reader] = EXECUTABLE_ORDINAL;
 
1602                                                 // see if a DylibLoadCommandsAtom has already been created for this install path
 
1603                                                 bool newDylib = true;
 
1604                                                 const char* dylibInstallPath = dylibInfo.reader->getInstallPath();
 
1605                                                 for (unsigned int seenLib=0; seenLib < i; ++seenLib) {
 
1606                                                         ExecutableFile::DyLibUsed& seenDylibInfo = dynamicLibraries[seenLib];
 
1607                                                         if ( !seenDylibInfo.options.fBundleLoader ) {
 
1608                                                                 const char* seenDylibInstallPath = seenDylibInfo.reader->getInstallPath();
 
1609                                                                 if ( strcmp(seenDylibInstallPath, dylibInstallPath) == 0 ) {
 
1610                                                                         fLibraryToOrdinal[dylibInfo.reader] = fLibraryToOrdinal[seenDylibInfo.reader];
 
1611                                                                         fLibraryToLoadCommand[dylibInfo.reader] = fLibraryToLoadCommand[seenDylibInfo.reader]; 
 
1612                                                                         fLibraryAliases[dylibInfo.reader] = seenDylibInfo.reader;
 
1620                                                         // assign new ordinal and check for other paired load commands
 
1621                                                         fLibraryToOrdinal[dylibInfo.reader] = ordinal++;
 
1622                                                         DylibLoadCommandsAtom<A>* dyliblc = new DylibLoadCommandsAtom<A>(*this, dylibInfo);
 
1623                                                         fLibraryToLoadCommand[dylibInfo.reader] = dyliblc;
 
1624                                                         fWriterSynthesizedAtoms.push_back(dyliblc);
 
1625                                                         if ( dylibInfo.options.fReExport 
 
1626                                                                 && (fOptions.macosxVersionMin() < ObjectFile::ReaderOptions::k10_5)
 
1627                                                                 && (fOptions.outputKind() == Options::kDynamicLibrary) ) {
 
1628                                                                 // see if child has sub-framework that is this
 
1629                                                                 bool isSubFramework = false;
 
1630                                                                 const char* childInUmbrella = dylibInfo.reader->parentUmbrella();
 
1631                                                                 if ( childInUmbrella != NULL ) {
 
1632                                                                         const char* myLeaf = strrchr(fOptions.installPath(), '/');
 
1633                                                                         if ( myLeaf != NULL ) {
 
1634                                                                                 if ( strcmp(childInUmbrella, &myLeaf[1]) == 0 )
 
1635                                                                                         isSubFramework = true;
 
1638                                                                 // LC_SUB_FRAMEWORK is in child, so do nothing in parent 
 
1639                                                                 if ( ! isSubFramework ) {
 
1640                                                                         // this dylib also needs a sub_x load command
 
1641                                                                         bool isFrameworkReExport = false;
 
1642                                                                         const char* lastSlash = strrchr(dylibInstallPath, '/');
 
1643                                                                         if ( lastSlash != NULL ) {
 
1644                                                                                 char frameworkName[strlen(lastSlash)+20];
 
1645                                                                                 sprintf(frameworkName, "/%s.framework/", &lastSlash[1]);
 
1646                                                                                 isFrameworkReExport = (strstr(dylibInstallPath, frameworkName) != NULL);
 
1648                                                                         if ( isFrameworkReExport ) {
 
1649                                                                                 // needs a LC_SUB_UMBRELLA command
 
1650                                                                                 fWriterSynthesizedAtoms.push_back(new SubUmbrellaLoadCommandsAtom<A>(*this, &lastSlash[1]));
 
1653                                                                                 // needs a LC_SUB_LIBRARY command
 
1654                                                                                 const char* nameStart = &lastSlash[1];
 
1655                                                                                 if ( lastSlash == NULL )
 
1656                                                                                         nameStart = dylibInstallPath;
 
1657                                                                                 int len = strlen(nameStart);
 
1658                                                                                 const char* dot = strchr(nameStart, '.');
 
1660                                                                                         len = dot - nameStart;
 
1661                                                                                 fWriterSynthesizedAtoms.push_back(new SubLibraryLoadCommandsAtom<A>(*this, nameStart, len));
 
1668                                 // add umbrella command if needed
 
1669                                 if ( fOptions.umbrellaName() != NULL ) {
 
1670                                         fWriterSynthesizedAtoms.push_back(new UmbrellaLoadCommandsAtom<A>(*this, fOptions.umbrellaName()));
 
1672                                 // add allowable client commands if used
 
1673                                 std::vector<const char*>& allowableClients = fOptions.allowableClients();
 
1674                                 for (std::vector<const char*>::iterator it=allowableClients.begin(); it != allowableClients.end(); ++it)
 
1675                                         fWriterSynthesizedAtoms.push_back(new AllowableClientLoadCommandsAtom<A>(*this, *it));
 
1678                 case Options::kStaticExecutable:
 
1679                 case Options::kObjectFile:
 
1680                 case Options::kDyld:
 
1683         fNoReExportedDylibs = !hasReExports;
 
1685         // add any rpath load commands
 
1686         for(std::vector<const char*>::const_iterator it=fOptions.rpaths().begin(); it != fOptions.rpaths().end(); ++it) {
 
1687                 fWriterSynthesizedAtoms.push_back(new RPathLoadCommandsAtom<A>(*this, *it));
 
1690         // set up fSlideable
 
1691         switch ( fOptions.outputKind() ) {
 
1692                 case Options::kObjectFile:
 
1693                 case Options::kStaticExecutable:
 
1696                 case Options::kDynamicExecutable:
 
1697                         fSlideable = fOptions.positionIndependentExecutable();
 
1699                 case Options::kDyld:
 
1700                 case Options::kDynamicLibrary:
 
1701                 case Options::kDynamicBundle:
 
1706         //fprintf(stderr, "ordinals table:\n");
 
1707         //for (std::map<class ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {
 
1708         //      fprintf(stderr, "%d <== %s\n", it->second, it->first->getPath());
 
1712 template <typename A>
 
1713 Writer<A>::~Writer()
 
1715         if ( fFilePath != NULL )
 
1716                 free((void*)fFilePath);
 
1717         if ( fSymbolTable != NULL )
 
1718                 delete [] fSymbolTable;
 
1722 // for ppc64, -mdynamic-no-pic only works in low 2GB, so we might need to split the zeropage into two segments
 
1723 template <>bool Writer<ppc64>::mightNeedPadSegment() { return (fOptions.zeroPageSize() >= 0x80000000ULL); }
 
1724 template <typename A> bool Writer<A>::mightNeedPadSegment() { return false; }
 
1727 template <typename A>
 
1728 ObjectFile::Atom* Writer<A>::getUndefinedProxyAtom(const char* name)
 
1730         if ( fOptions.outputKind() == Options::kObjectFile ) {
 
1731                 // when doing -r -exported_symbols_list, don't creat proxy for a symbol
 
1732                 // that is supposed to be exported.  We want an error instead
 
1733                 // <rdar://problem/5062685> ld does not report error when -r is used and exported symbols are not defined.
 
1734                 if ( fOptions.hasExportRestrictList() && fOptions.shouldExport(name) )
 
1737                         return new UndefinedSymbolProxyAtom<A>(*this, name);
 
1739         else if ( (fOptions.undefinedTreatment() != Options::kUndefinedError) || fOptions.allowedUndefined(name) )  
 
1740                 return new UndefinedSymbolProxyAtom<A>(*this, name);
 
1745 template <typename A>
 
1746 uint8_t Writer<A>::ordinalForLibrary(ObjectFile::Reader* lib)
 
1748         // flat namespace images use zero for all ordinals
 
1749         if (  fOptions.nameSpace() != Options::kTwoLevelNameSpace )
 
1752         // is an UndefinedSymbolProxyAtom
 
1754                 if ( fOptions.nameSpace() == Options::kTwoLevelNameSpace )
 
1755                         return DYNAMIC_LOOKUP_ORDINAL;
 
1757         std::map<class ObjectFile::Reader*, uint32_t>::iterator pos = fLibraryToOrdinal.find(lib);
 
1758         if ( pos != fLibraryToOrdinal.end() )
 
1761         throw "can't find ordinal for imported symbol";
 
1764 template <typename A>
 
1765 ObjectFile::Atom& Writer<A>::makeObjcInfoAtom(ObjectFile::Reader::ObjcConstraint objcContraint, bool objcReplacementClasses)
 
1767         return *(new ObjCInfoAtom<A>(*this, objcContraint, objcReplacementClasses));
 
1771 template <typename A>
 
1772 uint64_t Writer<A>::write(std::vector<class ObjectFile::Atom*>& atoms,
 
1773                                                   std::vector<class ObjectFile::Reader::Stab>& stabs,
 
1774                                                   class ObjectFile::Atom* entryPointAtom, class ObjectFile::Atom* dyldHelperAtom,
 
1775                                                   bool createUUID, bool canScatter, ObjectFile::Reader::CpuConstraint cpuConstraint,
 
1776                                                   bool biggerThanTwoGigs)
 
1780         fEntryPoint = entryPointAtom;
 
1781         fDyldHelper = dyldHelperAtom;
 
1782         fCanScatter = canScatter;
 
1783         fCpuConstraint = cpuConstraint;
 
1784         fBiggerThanTwoGigs = biggerThanTwoGigs;
 
1787                 // Set for create UUID
 
1789                         fUUIDAtom->generate();
 
1791                 // remove uneeded dylib load commands
 
1792                 optimizeDylibReferences();
 
1794                 // check for mdynamic-no-pic codegen which force code into low 4GB
 
1795                 scanForAbsoluteReferences();
 
1797                 // create inter-library stubs
 
1800                 // create SegmentInfo and SectionInfo objects and assign all atoms to a section
 
1801                 partitionIntoSections();
 
1803                 // segment load command can now be sized and padding can be set
 
1804                 adjustLoadCommandsAndPadding();
 
1806                 // assign each section a file offset
 
1807                 assignFileOffsets();
 
1809                 // if need to add branch islands, reassign file offsets
 
1810                 if ( addBranchIslands() )
 
1811                         assignFileOffsets();
 
1813                 // build symbol table and relocations
 
1816                 // write map file if requested
 
1820                 return writeAtoms();
 
1822                 // clean up if any errors
 
1823                 close(fFileDescriptor);
 
1824                 (void)unlink(fFilePath);
 
1829 template <typename A>
 
1830 void Writer<A>::buildLinkEdit()
 
1832         this->collectExportedAndImportedAndLocalAtoms();
 
1833         this->buildSymbolTable();
 
1834         this->buildFixups();
 
1835         this->adjustLinkEditSections();
 
1840 template <typename A>
 
1841 uint64_t Writer<A>::getAtomLoadAddress(const ObjectFile::Atom* atom)
 
1843         return atom->getAddress();
 
1844 //      SectionInfo* info = (SectionInfo*)atom->getSection();
 
1845 //      return info->getBaseAddress() + atom->getSectionOffset();
 
1850 const char* Writer<x86_64>::symbolTableName(const ObjectFile::Atom* atom)
 
1852         static unsigned int counter = 0;
 
1853         const char* name = atom->getName();
 
1854         if ( strncmp(name, "cstring=", 8) == 0 )
 
1855                 asprintf((char**)&name, "LC%u", counter++);
 
1859 template <typename A>
 
1860 const char* Writer<A>::symbolTableName(const ObjectFile::Atom* atom)
 
1862         return atom->getName();
 
1865 template <typename A>
 
1866 void Writer<A>::setExportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry)
 
1869         entry->set_n_strx(this->fStringsAtom->add(this->symbolTableName(atom)));
 
1872         if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableInAsAbsolute ) {
 
1873                 entry->set_n_type(N_EXT | N_ABS);
 
1876                 entry->set_n_type(N_EXT | N_SECT);
 
1877                 if ( (atom->getScope() == ObjectFile::Atom::scopeLinkageUnit) && (fOptions.outputKind() == Options::kObjectFile) ) {
 
1878                         if ( fOptions.keepPrivateExterns() )
 
1879                                 entry->set_n_type(N_EXT | N_SECT | N_PEXT);
 
1883         // set n_sect (section number of implementation )
 
1884         uint8_t sectionIndex = atom->getSection()->getIndex();
 
1885         entry->set_n_sect(sectionIndex);
 
1887         // the __mh_execute_header is magic and must be an absolute symbol
 
1888         if ( (sectionIndex==0) 
 
1889                 && (fOptions.outputKind() == Options::kDynamicExecutable)
 
1890                 && (atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableInAndNeverStrip ))
 
1891                 entry->set_n_type(N_EXT | N_ABS);
 
1895         if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableInAndNeverStrip )
 
1896                 desc |= REFERENCED_DYNAMICALLY;
 
1897         if ( atom->getDefinitionKind() == ObjectFile::Atom::kWeakDefinition ) {
 
1899                 fHasWeakExports = true;
 
1901         entry->set_n_desc(desc);
 
1903         // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
 
1904         if ( atom->getDefinitionKind() == ObjectFile::Atom::kAbsoluteSymbol ) 
 
1905                 entry->set_n_value(atom->getSectionOffset());
 
1907                 entry->set_n_value(this->getAtomLoadAddress(atom));
 
1910 template <typename A>
 
1911 void Writer<A>::setImportNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry)
 
1914         entry->set_n_strx(this->fStringsAtom->add(atom->getName()));
 
1917         if ( (fOptions.outputKind() == Options::kObjectFile) 
 
1918                 && (atom->getScope() == ObjectFile::Atom::scopeLinkageUnit) 
 
1919                 && (atom->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition) )
 
1920                 entry->set_n_type(N_UNDF | N_EXT | N_PEXT);
 
1921         else if ( fOptions.prebind() )
 
1922                 entry->set_n_type(N_PBUD | N_EXT);
 
1924                 entry->set_n_type(N_UNDF | N_EXT);
 
1927         entry->set_n_sect(0);
 
1930         if ( fOptions.outputKind() != Options::kObjectFile ) {
 
1931                 // set n_desc ( high byte is library ordinal, low byte is reference type )
 
1932                 std::map<const ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fStubsMap.find(atom);
 
1933                 if ( pos != fStubsMap.end() )
 
1934                         desc = REFERENCE_FLAG_UNDEFINED_LAZY;
 
1936                         desc = REFERENCE_FLAG_UNDEFINED_NON_LAZY;
 
1938                         uint8_t ordinal = this->ordinalForLibrary(atom->getFile());
 
1939                         //fprintf(stderr, "ordinal=%u from reader=%p for symbol=%s\n", ordinal, atom->getFile(), atom->getName());
 
1940                         SET_LIBRARY_ORDINAL(desc, ordinal);
 
1942                 catch (const char* msg) {
 
1943                         throwf("%s %s from %s", msg, atom->getDisplayName(), atom->getFile()->getPath());
 
1946         else if ( atom->getDefinitionKind() == ObjectFile::Atom::kTentativeDefinition ) {
 
1947                 uint8_t align = atom->getAlignment().powerOf2;
 
1948                 // if alignment does not match size, then record the custom alignment
 
1949                 if ( align != __builtin_ctz(atom->getSize()) )
 
1950                         SET_COMM_ALIGN(desc, align);
 
1952         if ( atom->getSymbolTableInclusion() == ObjectFile::Atom::kSymbolTableInAndNeverStrip )
 
1953                 desc |= REFERENCED_DYNAMICALLY;
 
1954         if ( ( fOptions.outputKind() != Options::kObjectFile) && (atom->getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
 
1955                 desc |= N_REF_TO_WEAK;
 
1956                 fReferencesWeakImports = true;
 
1958         // set weak_import attribute
 
1959         if ( fWeakImportMap[atom] )
 
1961         entry->set_n_desc(desc);
 
1963         // set n_value, zero for import proxy and size for tentative definition
 
1964         entry->set_n_value(atom->getSize());
 
1968 template <typename A>
 
1969 void Writer<A>::setLocalNlist(const ObjectFile::Atom* atom, macho_nlist<P>* entry)
 
1972         const char* symbolName = this->symbolTableName(atom);
 
1974         if ( (fOptions.outputKind() == Options::kObjectFile) && !fOptions.keepLocalSymbol(symbolName) ) {
 
1975                 sprintf(anonName, "l%u", fAnonNameIndex++);
 
1976                 symbolName = anonName;
 
1978         entry->set_n_strx(this->fStringsAtom->add(symbolName));
 
1981         uint8_t type = N_SECT;
 
1982         if ( atom->getDefinitionKind() == ObjectFile::Atom::kAbsoluteSymbol ) 
 
1984         if ( atom->getScope() == ObjectFile::Atom::scopeLinkageUnit )
 
1986         entry->set_n_type(type);
 
1988         // set n_sect (section number of implementation )
 
1989         uint8_t sectIndex = atom->getSection()->getIndex();
 
1990         if ( sectIndex == 0 ) {
 
1991                 // see <mach-o/ldsyms.h> synthesized lable for mach_header needs special section number...
 
1992                 if ( strcmp(atom->getSectionName(), "._mach_header") == 0 )
 
1995         entry->set_n_sect(sectIndex);
 
1999         if ( atom->getDefinitionKind() == ObjectFile::Atom::kWeakDefinition )
 
2001         entry->set_n_desc(desc);
 
2003         // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
 
2004         if ( atom->getDefinitionKind() == ObjectFile::Atom::kAbsoluteSymbol ) 
 
2005                 entry->set_n_value(atom->getSectionOffset());
 
2007                 entry->set_n_value(this->getAtomLoadAddress(atom));
 
2011 template <typename A>
 
2012 void Writer<A>::addLocalLabel(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* name)
 
2014         macho_nlist<P> entry;
 
2017         entry.set_n_strx(fStringsAtom->add(name));
 
2020         entry.set_n_type(N_SECT);
 
2022         // set n_sect (section number of implementation )
 
2023         entry.set_n_sect(atom.getSection()->getIndex());
 
2026         entry.set_n_desc(0);
 
2028         // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
 
2029         entry.set_n_value(this->getAtomLoadAddress(&atom) + offsetInAtom);
 
2032         fLocalExtraLabels.push_back(entry);
 
2037 template <typename A>
 
2038 void Writer<A>::addGlobalLabel(ObjectFile::Atom& atom, uint32_t offsetInAtom, const char* name)
 
2040         macho_nlist<P> entry;
 
2043         entry.set_n_strx(fStringsAtom->add(name));
 
2046         entry.set_n_type(N_SECT|N_EXT);
 
2048         // set n_sect (section number of implementation )
 
2049         entry.set_n_sect(atom.getSection()->getIndex());
 
2052         entry.set_n_desc(0);
 
2054         // set n_value ( address this symbol will be at if this executable is loaded at it preferred address )
 
2055         entry.set_n_value(this->getAtomLoadAddress(&atom) + offsetInAtom);
 
2058         fGlobalExtraLabels.push_back(entry);
 
2061 template <typename A>
 
2062 void Writer<A>::setNlistRange(std::vector<class ObjectFile::Atom*>& atoms, uint32_t startIndex, uint32_t count)
 
2064         macho_nlist<P>* entry = &fSymbolTable[startIndex];
 
2065         for (uint32_t i=0; i < count; ++i, ++entry) {
 
2066                 ObjectFile::Atom* atom = atoms[i];
 
2067                 if ( &atoms == &fExportedAtoms ) {
 
2068                         this->setExportNlist(atom, entry);
 
2070                 else if ( &atoms == &fImportedAtoms ) {
 
2071                         this->setImportNlist(atom, entry);
 
2074                         this->setLocalNlist(atom, entry);
 
2079 template <typename A>
 
2080 void Writer<A>::copyNlistRange(const std::vector<macho_nlist<P> >& entries, uint32_t startIndex)
 
2082         for ( typename std::vector<macho_nlist<P> >::const_iterator it = entries.begin(); it != entries.end(); ++it) 
 
2083                 fSymbolTable[startIndex++] = *it;
 
2087 template <typename A>
 
2088 struct NListNameSorter
 
2090         NListNameSorter(StringsLinkEditAtom<A>* pool) : fStringPool(pool) {}
 
2092      bool operator()(const macho_nlist<typename A::P>& left, const macho_nlist<typename A::P>& right)
 
2094           return (strcmp(fStringPool->stringForIndex(left.n_strx()), fStringPool->stringForIndex(right.n_strx())) < 0);
 
2097         StringsLinkEditAtom<A>*         fStringPool;
 
2101 template <typename A>
 
2102 void Writer<A>::buildSymbolTable()
 
2104         fSymbolTableStabsStartIndex             = 0;
 
2105         fSymbolTableStabsCount                  = fStabs->size();
 
2106         fSymbolTableLocalStartIndex             = fSymbolTableStabsStartIndex + fSymbolTableStabsCount;
 
2107         fSymbolTableLocalCount                  = fLocalSymbolAtoms.size() + fLocalExtraLabels.size();
 
2108         fSymbolTableExportStartIndex    = fSymbolTableLocalStartIndex + fSymbolTableLocalCount;
 
2109         fSymbolTableExportCount                 = fExportedAtoms.size() + fGlobalExtraLabels.size();
 
2110         fSymbolTableImportStartIndex    = fSymbolTableExportStartIndex + fSymbolTableExportCount;
 
2111         fSymbolTableImportCount                 = fImportedAtoms.size();
 
2113         // allocate symbol table
 
2114         fSymbolTableCount = fSymbolTableStabsCount + fSymbolTableLocalCount + fSymbolTableExportCount + fSymbolTableImportCount;
 
2115         fSymbolTable = new macho_nlist<P>[fSymbolTableCount];
 
2117         // fill in symbol table and string pool (do stabs last so strings are at end of pool)
 
2118         setNlistRange(fLocalSymbolAtoms, fSymbolTableLocalStartIndex,  fLocalSymbolAtoms.size());
 
2119         if ( fLocalExtraLabels.size() != 0 )
 
2120                 copyNlistRange(fLocalExtraLabels, fSymbolTableLocalStartIndex+fLocalSymbolAtoms.size());
 
2121         setNlistRange(fExportedAtoms,    fSymbolTableExportStartIndex, fExportedAtoms.size());
 
2122         if ( fGlobalExtraLabels.size() != 0 ) {
 
2123                 copyNlistRange(fGlobalExtraLabels, fSymbolTableExportStartIndex+fExportedAtoms.size());
 
2124                 // re-sort combined range
 
2125                 std::sort(  &fSymbolTable[fSymbolTableExportStartIndex], 
 
2126                                         &fSymbolTable[fSymbolTableExportStartIndex+fSymbolTableExportCount], 
 
2127                                         NListNameSorter<A>(fStringsAtom) );
 
2129         setNlistRange(fImportedAtoms,    fSymbolTableImportStartIndex, fSymbolTableImportCount);
 
2130         addStabs(fSymbolTableStabsStartIndex);
 
2132         // set up module table
 
2133         if ( fModuleInfoAtom != NULL )
 
2134                 fModuleInfoAtom->setName();
 
2139 template <typename A>
 
2140 bool Writer<A>::shouldExport(const ObjectFile::Atom& atom) const
 
2142         switch ( atom.getSymbolTableInclusion() ) {
 
2143                 case ObjectFile::Atom::kSymbolTableNotIn:
 
2145                 case ObjectFile::Atom::kSymbolTableInAndNeverStrip:
 
2147                 case ObjectFile::Atom::kSymbolTableInAsAbsolute:
 
2148                 case ObjectFile::Atom::kSymbolTableIn:
 
2149                         switch ( atom.getScope() ) {
 
2150                                 case ObjectFile::Atom::scopeGlobal:
 
2152                                 case ObjectFile::Atom::scopeLinkageUnit:
 
2153                                         return ( (fOptions.outputKind() == Options::kObjectFile) && fOptions.keepPrivateExterns() );
 
2162 template <typename A>
 
2163 void Writer<A>::collectExportedAndImportedAndLocalAtoms()
 
2165         const int atomCount = fAllAtoms->size();
 
2166         // guess at sizes of each bucket to minimize re-allocations
 
2167         fImportedAtoms.reserve(100);
 
2168         fExportedAtoms.reserve(atomCount/2);
 
2169         fLocalSymbolAtoms.reserve(atomCount);
 
2170         for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
2171                 ObjectFile::Atom* atom = *it;
 
2172                 // only named atoms go in symbol table
 
2173                 if ( atom->getName() != NULL ) {
 
2174                         // put atom into correct bucket: imports, exports, locals
 
2175                         //fprintf(stderr, "collectExportedAndImportedAndLocalAtoms() name=%s\n", atom->getDisplayName());
 
2176                         switch ( atom->getDefinitionKind() ) {
 
2177                                 case ObjectFile::Atom::kExternalDefinition:
 
2178                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
2179                                         fImportedAtoms.push_back(atom);
 
2181                                 case ObjectFile::Atom::kTentativeDefinition:
 
2182                                         if ( (fOptions.outputKind() == Options::kObjectFile) && !fOptions.readerOptions().fMakeTentativeDefinitionsReal ) {
 
2183                                                 fImportedAtoms.push_back(atom);
 
2187                                 case ObjectFile::Atom::kRegularDefinition:
 
2188                                 case ObjectFile::Atom::kWeakDefinition:
 
2189                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
2190                                         if ( this->shouldExport(*atom) )
 
2191                                                 fExportedAtoms.push_back(atom);
 
2192                                         else if ( (atom->getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn)
 
2193                                                 && ((fOptions.outputKind() == Options::kObjectFile) || fOptions.keepLocalSymbol(atom->getName())) )
 
2194                                                 fLocalSymbolAtoms.push_back(atom);
 
2198                 // when geneating a .o file, dtrace static probes become local labels
 
2199                 if ( fOptions.outputKind() == Options::kObjectFile) {
 
2200                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
2201                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
2202                                 ObjectFile::Reference* ref = *rit;
 
2203                                 if ( ref->getKind() == A::kDtraceProbe ) {
 
2204                                         // dtrace probe points to be add back into generated .o file
 
2205                                         this->addLocalLabel(*atom, ref->getFixUpOffset(), ref->getTargetName());
 
2209                 // when linking kernel, old style dtrace static probes become global labels
 
2210                 else if ( fOptions.outputKind() == Options::kStaticExecutable ) {
 
2211                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
2212                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
2213                                 ObjectFile::Reference* ref = *rit;
 
2214                                 if ( ref->getKind() == A::kDtraceProbe ) {
 
2215                                         // dtrace probe points to be add back into generated .o file
 
2216                                         this->addGlobalLabel(*atom, ref->getFixUpOffset(), ref->getTargetName());
 
2222         // sort exported atoms by name
 
2223         std::sort(fExportedAtoms.begin(), fExportedAtoms.end(), AtomByNameSorter());
 
2224         // sort imported atoms by name (not required by runtime, but helps make generated files binary diffable)
 
2225         std::sort(fImportedAtoms.begin(), fImportedAtoms.end(), AtomByNameSorter());
 
2229 template <typename A>
 
2230 uint64_t Writer<A>::valueForStab(const ObjectFile::Reader::Stab& stab)
 
2232         switch ( stab.type ) {
 
2234                         if ( (stab.string == NULL) || (strlen(stab.string) == 0) ) {
 
2235                                 // end of function N_FUN has size
 
2236                                 return stab.atom->getSize();
 
2239                                 // start of function N_FUN has address
 
2240                                 return getAtomLoadAddress(stab.atom);
 
2245                         if ( stab.atom == NULL )
 
2246                                 // some weird assembly files have slines not associated with a function
 
2249                                 // all these stab types need their value changed from an offset in the atom to an address
 
2250                                 return getAtomLoadAddress(stab.atom) + stab.value;
 
2254                         // all these need address of atom
 
2255                         return getAtomLoadAddress(stab.atom);;
 
2257                         return stab.atom->getSize();
 
2259                         if ( stab.atom == NULL ) {
 
2263                                 if ( (stab.string == NULL) || (strlen(stab.string) == 0) ) {
 
2264                                         // end of translation unit N_SO has address of end of last atom
 
2265                                         return getAtomLoadAddress(stab.atom) + stab.atom->getSize();
 
2268                                         // start of translation unit N_SO has address of end of first atom
 
2269                                         return getAtomLoadAddress(stab.atom);
 
2278 template <typename A>
 
2279 uint32_t Writer<A>::stringOffsetForStab(const ObjectFile::Reader::Stab& stab)
 
2281         switch (stab.type) {
 
2283                         if ( (stab.string == NULL) || stab.string[0] == '\0' ) {
 
2284                                 return this->fStringsAtom->emptyString();
 
2287                         // fall into uniquing case
 
2291                         return this->fStringsAtom->addUnique(stab.string);
 
2294                         if ( stab.string == NULL )
 
2296                         else if ( stab.string[0] == '\0' )
 
2297                                 return this->fStringsAtom->emptyString();
 
2299                                 return this->fStringsAtom->add(stab.string);
 
2304 template <typename A>
 
2305 uint8_t Writer<A>::sectionIndexForStab(const ObjectFile::Reader::Stab& stab)
 
2307         // in FUN stabs, n_sect field is 0 for start FUN and 1 for end FUN
 
2308         if ( stab.type == N_FUN )
 
2310         else if ( stab.atom != NULL ) 
 
2311                 return stab.atom->getSection()->getIndex();
 
2316 template <typename A>
 
2317 void Writer<A>::addStabs(uint32_t startIndex)
 
2319         macho_nlist<P>* entry = &fSymbolTable[startIndex];
 
2320         for(std::vector<ObjectFile::Reader::Stab>::iterator it = fStabs->begin(); it != fStabs->end(); ++it, ++entry) {
 
2321                 const ObjectFile::Reader::Stab& stab = *it;
 
2322                 entry->set_n_type(stab.type);
 
2323                 entry->set_n_sect(sectionIndexForStab(stab));
 
2324                 entry->set_n_desc(stab.desc);
 
2325                 entry->set_n_value(valueForStab(stab));
 
2326                 entry->set_n_strx(stringOffsetForStab(stab));
 
2332 template <typename A>
 
2333 uint32_t Writer<A>::symbolIndex(ObjectFile::Atom& atom)
 
2337         for(std::vector<ObjectFile::Atom*>::iterator it=fImportedAtoms.begin(); it != fImportedAtoms.end(); ++it) {
 
2339                         return i + fSymbolTableImportStartIndex;
 
2345         for(std::vector<ObjectFile::Atom*>::iterator it=fLocalSymbolAtoms.begin(); it != fLocalSymbolAtoms.end(); ++it) {
 
2347                         return i + fSymbolTableLocalStartIndex;
 
2353         for(std::vector<ObjectFile::Atom*>::iterator it=fExportedAtoms.begin(); it != fExportedAtoms.end(); ++it) {
 
2355                         return i + fSymbolTableExportStartIndex;
 
2359         throwf("atom not found in symbolIndex(%s) for %s", atom.getDisplayName(), atom.getFile()->getPath());
 
2364 bool Writer<x86_64>::makesExternalRelocatableReference(ObjectFile::Atom& target) const
 
2366         switch ( target.getSymbolTableInclusion() )      {
 
2367                 case ObjectFile::Atom::kSymbolTableNotIn:
 
2369                 case ObjectFile::Atom::kSymbolTableInAsAbsolute:
 
2370                 case ObjectFile::Atom::kSymbolTableIn:
 
2371                 case ObjectFile::Atom::kSymbolTableInAndNeverStrip:
 
2377 template <typename A>
 
2378 bool Writer<A>::makesExternalRelocatableReference(ObjectFile::Atom& target) const
 
2380         switch ( target.getDefinitionKind() ) {
 
2381                 case ObjectFile::Atom::kRegularDefinition:
 
2382                 case ObjectFile::Atom::kWeakDefinition:
 
2383                 case ObjectFile::Atom::kAbsoluteSymbol:
 
2385                 case ObjectFile::Atom::kTentativeDefinition:
 
2386                         return (target.getScope() != ObjectFile::Atom::scopeTranslationUnit);
 
2387                 case ObjectFile::Atom::kExternalDefinition:
 
2388                 case ObjectFile::Atom::kExternalWeakDefinition:
 
2389                         return shouldExport(target);
 
2394 template <typename A>
 
2395 void Writer<A>::buildFixups()
 
2397         if ( fOptions.outputKind() == Options::kObjectFile ) {
 
2398                 this->buildObjectFileFixups();
 
2401                 if ( fOptions.keepRelocations() )
 
2402                         this->buildObjectFileFixups();
 
2403                 this->buildExecutableFixups();
 
2408 uint32_t Writer<x86_64>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 
2410         ObjectFile::Atom& target = ref->getTarget();
 
2411         bool external = this->makesExternalRelocatableReference(target);
 
2412         uint32_t symbolIndex = external ? this->symbolIndex(target) : target.getSection()->getIndex();
 
2413         uint32_t address = atom->getSectionOffset()+ref->getFixUpOffset();
 
2414         macho_relocation_info<P> reloc1;
 
2415         macho_relocation_info<P> reloc2;
 
2416         x86_64::ReferenceKinds kind = (x86_64::ReferenceKinds)ref->getKind();
 
2419                 case x86_64::kNoFixUp:
 
2420                 case x86_64::kFollowOn:
 
2423                 case x86_64::kPointer:
 
2424                 case x86_64::kPointerWeakImport:
 
2425                         reloc1.set_r_address(address);
 
2426                         reloc1.set_r_symbolnum(symbolIndex);
 
2427                         reloc1.set_r_pcrel(false);
 
2428                         reloc1.set_r_length(3);
 
2429                         reloc1.set_r_extern(external);
 
2430                         reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
 
2431                         fSectionRelocs.push_back(reloc1);
 
2434                 case x86_64::kPointerDiff32:
 
2435                 case x86_64::kPointerDiff:      
 
2437                         ObjectFile::Atom& fromTarget = ref->getFromTarget();
 
2438                         bool fromExternal = (fromTarget.getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn);
 
2439                         uint32_t fromSymbolIndex = fromExternal ? this->symbolIndex(fromTarget) : fromTarget.getSection()->getIndex();
 
2440                         reloc1.set_r_address(address);
 
2441                         reloc1.set_r_symbolnum(symbolIndex);
 
2442                         reloc1.set_r_pcrel(false);
 
2443                         reloc1.set_r_length(kind==x86_64::kPointerDiff32 ? 2 : 3);
 
2444                         reloc1.set_r_extern(external);
 
2445                         reloc1.set_r_type(X86_64_RELOC_UNSIGNED);
 
2446                         reloc2.set_r_address(address);
 
2447                         reloc2.set_r_symbolnum(fromSymbolIndex);
 
2448                         reloc2.set_r_pcrel(false);
 
2449                         reloc2.set_r_length(kind==x86_64::kPointerDiff32 ? 2 : 3);
 
2450                         reloc2.set_r_extern(fromExternal);
 
2451                         reloc2.set_r_type(X86_64_RELOC_SUBTRACTOR);
 
2452                         fSectionRelocs.push_back(reloc1);
 
2453                         fSectionRelocs.push_back(reloc2);
 
2457                 case x86_64::kBranchPCRel32:
 
2458                 case x86_64::kBranchPCRel32WeakImport:
 
2459                 case x86_64::kDtraceProbeSite:
 
2460                 case x86_64::kDtraceIsEnabledSite:
 
2461                         reloc1.set_r_address(address);
 
2462                         reloc1.set_r_symbolnum(symbolIndex);
 
2463                         reloc1.set_r_pcrel(true);
 
2464                         reloc1.set_r_length(2);
 
2465                         reloc1.set_r_extern(external);
 
2466                         reloc1.set_r_type(X86_64_RELOC_BRANCH);
 
2467                         fSectionRelocs.push_back(reloc1);
 
2470                 case x86_64::kPCRel32:
 
2471                         reloc1.set_r_address(address);
 
2472                         reloc1.set_r_symbolnum(symbolIndex);
 
2473                         reloc1.set_r_pcrel(true);
 
2474                         reloc1.set_r_length(2);
 
2475                         reloc1.set_r_extern(external);
 
2476                         reloc1.set_r_type(X86_64_RELOC_SIGNED);
 
2477                         fSectionRelocs.push_back(reloc1);
 
2480                 case x86_64::kPCRel32_1:
 
2481                         reloc1.set_r_address(address);
 
2482                         reloc1.set_r_symbolnum(symbolIndex);
 
2483                         reloc1.set_r_pcrel(true);
 
2484                         reloc1.set_r_length(2);
 
2485                         reloc1.set_r_extern(external);
 
2486                         reloc1.set_r_type(X86_64_RELOC_SIGNED_1);
 
2487                         fSectionRelocs.push_back(reloc1);
 
2490                 case x86_64::kPCRel32_2:
 
2491                         reloc1.set_r_address(address);
 
2492                         reloc1.set_r_symbolnum(symbolIndex);
 
2493                         reloc1.set_r_pcrel(true);
 
2494                         reloc1.set_r_length(2);
 
2495                         reloc1.set_r_extern(external);
 
2496                         reloc1.set_r_type(X86_64_RELOC_SIGNED_2);
 
2497                         fSectionRelocs.push_back(reloc1);
 
2500                 case x86_64::kPCRel32_4:
 
2501                         reloc1.set_r_address(address);
 
2502                         reloc1.set_r_symbolnum(symbolIndex);
 
2503                         reloc1.set_r_pcrel(true);
 
2504                         reloc1.set_r_length(2);
 
2505                         reloc1.set_r_extern(external);
 
2506                         reloc1.set_r_type(X86_64_RELOC_SIGNED_4);
 
2507                         fSectionRelocs.push_back(reloc1);
 
2510                 case x86_64::kPCRel32GOT:
 
2511                 case x86_64::kPCRel32GOTWeakImport:
 
2512                         reloc1.set_r_address(address);
 
2513                         reloc1.set_r_symbolnum(symbolIndex);
 
2514                         reloc1.set_r_pcrel(true);
 
2515                         reloc1.set_r_length(2);
 
2516                         reloc1.set_r_extern(external);
 
2517                         reloc1.set_r_type(X86_64_RELOC_GOT);
 
2518                         fSectionRelocs.push_back(reloc1);
 
2521                 case x86_64::kPCRel32GOTLoad:
 
2522                 case x86_64::kPCRel32GOTLoadWeakImport:
 
2523                         reloc1.set_r_address(address);
 
2524                         reloc1.set_r_symbolnum(symbolIndex);
 
2525                         reloc1.set_r_pcrel(true);
 
2526                         reloc1.set_r_length(2);
 
2527                         reloc1.set_r_extern(external);
 
2528                         reloc1.set_r_type(X86_64_RELOC_GOT_LOAD);
 
2529                         fSectionRelocs.push_back(reloc1);
 
2532                 case x86_64::kDtraceTypeReference:
 
2533                 case x86_64::kDtraceProbe:
 
2534                         // generates no relocs
 
2542 uint32_t Writer<x86>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 
2544         ObjectFile::Atom& target = ref->getTarget();
 
2545         bool isExtern = this->makesExternalRelocatableReference(target);
 
2546         uint32_t symbolIndex = 0;
 
2548                 symbolIndex = this->symbolIndex(target);
 
2549         uint32_t sectionNum = target.getSection()->getIndex();
 
2550         uint32_t address = atom->getSectionOffset()+ref->getFixUpOffset();
 
2551         macho_relocation_info<P> reloc1;
 
2552         macho_relocation_info<P> reloc2;
 
2553         macho_scattered_relocation_info<P>* sreloc1 = (macho_scattered_relocation_info<P>*)&reloc1;
 
2554         macho_scattered_relocation_info<P>* sreloc2 = (macho_scattered_relocation_info<P>*)&reloc2;
 
2555         x86::ReferenceKinds kind = (x86::ReferenceKinds)ref->getKind();
 
2557         if ( !isExtern && (sectionNum == 0) && (target.getDefinitionKind() != ObjectFile::Atom::kAbsoluteSymbol) )
 
2558                 fprintf(stderr, "ld: warning section index == 0 for %s (kind=%d, scope=%d, inclusion=%d) in %s\n",
 
2559                  target.getDisplayName(), target.getDefinitionKind(), target.getScope(), target.getSymbolTableInclusion(), target.getFile()->getPath());
 
2564                 case x86::kFollowOn:
 
2568                 case x86::kPointerWeakImport:
 
2569                 case x86::kAbsolute32:
 
2570                         if ( !isExtern && (ref->getTargetOffset() != 0) ) {
 
2571                                 // use scattered reloc is target offset is non-zero
 
2572                                 sreloc1->set_r_scattered(true);
 
2573                                 sreloc1->set_r_pcrel(false);
 
2574                                 sreloc1->set_r_length(2);
 
2575                                 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
 
2576                                 sreloc1->set_r_address(address);
 
2577                                 sreloc1->set_r_value(target.getAddress());
 
2580                                 reloc1.set_r_address(address);
 
2581                                 reloc1.set_r_symbolnum(isExtern ? symbolIndex : sectionNum);
 
2582                                 reloc1.set_r_pcrel(false);
 
2583                                 reloc1.set_r_length(2);
 
2584                                 reloc1.set_r_extern(isExtern);
 
2585                                 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
 
2587                         fSectionRelocs.push_back(reloc1);
 
2590                 case x86::kPointerDiff16:
 
2591                 case x86::kPointerDiff:
 
2593                                 //pint_t fromAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
 
2594                                 //fprintf(stderr, "addObjectRelocs(): refFromTarget=%s, refTarget=%s, refFromTargetAddr=0x%llX, refFromTargetOffset=0x%llX\n",
 
2595                                 //                      ref->getFromTarget().getDisplayName(), ref->getTarget().getDisplayName(), 
 
2596                                 //                      ref->getFromTarget().getAddress(), ref->getFromTargetOffset());
 
2597                                 sreloc1->set_r_scattered(true);
 
2598                                 sreloc1->set_r_pcrel(false);
 
2599                                 sreloc1->set_r_length( (kind==x86::kPointerDiff) ? 2 : 1 );
 
2600                                 if ( ref->getTarget().getScope() == ObjectFile::Atom::scopeTranslationUnit )
 
2601                                         sreloc1->set_r_type(GENERIC_RELOC_LOCAL_SECTDIFF);
 
2603                                         sreloc1->set_r_type(GENERIC_RELOC_SECTDIFF);
 
2604                                 sreloc1->set_r_address(address);
 
2605                                 sreloc1->set_r_value(target.getAddress());
 
2606                                 sreloc2->set_r_scattered(true);
 
2607                                 sreloc2->set_r_pcrel(false);
 
2608                                 sreloc2->set_r_length( (kind==x86::kPointerDiff) ? 2 : 1 );
 
2609                                 sreloc2->set_r_type(GENERIC_RELOC_PAIR);
 
2610                                 sreloc2->set_r_address(0);
 
2611                                 //if ( &ref->getFromTarget() == &ref->getTarget() )
 
2612                                         sreloc2->set_r_value(ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
2614                                 //      sreloc2->set_r_value(ref->getFromTarget().getAddress());
 
2615                                 fSectionRelocs.push_back(reloc2);
 
2616                                 fSectionRelocs.push_back(reloc1);
 
2620                 case x86::kPCRel32WeakImport:
 
2623                 case x86::kDtraceProbeSite:
 
2624                 case x86::kDtraceIsEnabledSite:
 
2625                         if ( !isExtern && (ref->getTargetOffset() != 0) ) {
 
2626                                 // use scattered reloc is target offset is non-zero
 
2627                                 sreloc1->set_r_scattered(true);
 
2628                                 sreloc1->set_r_pcrel(true);
 
2629                                 sreloc1->set_r_length( (kind==x86::kPCRel16) ? 1 : 2);
 
2630                                 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
 
2631                                 sreloc1->set_r_address(address);
 
2632                                 sreloc1->set_r_value(target.getAddress());
 
2635                                 reloc1.set_r_address(address);
 
2636                                 reloc1.set_r_symbolnum(isExtern ? symbolIndex : sectionNum);
 
2637                                 reloc1.set_r_pcrel(true);
 
2638                                 reloc1.set_r_length( (kind==x86::kPCRel16) ? 1 : 2);
 
2639                                 reloc1.set_r_extern(isExtern);
 
2640                                 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
 
2642                         fSectionRelocs.push_back(reloc1);
 
2645                 case x86::kDtraceTypeReference:
 
2646                 case x86::kDtraceProbe:
 
2647                         // generates no relocs
 
2657 template <> uint64_t    Writer<ppc>::maxAddress() { return 0xFFFFFFFFULL; }
 
2658 template <> uint64_t  Writer<ppc64>::maxAddress() { return 0xFFFFFFFFFFFFFFFFULL; }
 
2659 template <> uint64_t    Writer<x86>::maxAddress() { return 0xFFFFFFFFULL; }
 
2660 template <> uint64_t Writer<x86_64>::maxAddress() { return 0xFFFFFFFFFFFFFFFFULL; }
 
2664 uint8_t Writer<ppc>::getRelocPointerSize()
 
2670 uint8_t Writer<ppc64>::getRelocPointerSize()
 
2676 uint32_t Writer<ppc>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 
2678         return addObjectRelocs_powerpc(atom, ref);
 
2682 uint32_t Writer<ppc64>::addObjectRelocs(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 
2684         return addObjectRelocs_powerpc(atom, ref);
 
2688 // addObjectRelocs<ppc> and addObjectRelocs<ppc64> are almost exactly the same, so
 
2689 // they use a common addObjectRelocs_powerpc() method.
 
2691 template <typename A>
 
2692 uint32_t Writer<A>::addObjectRelocs_powerpc(ObjectFile::Atom* atom, ObjectFile::Reference* ref)
 
2694         ObjectFile::Atom& target = ref->getTarget();
 
2695         bool isExtern = this->makesExternalRelocatableReference(target);        
 
2696         uint32_t symbolIndex = 0;
 
2698                 symbolIndex = this->symbolIndex(target);
 
2699         uint32_t sectionNum = target.getSection()->getIndex();
 
2700         uint32_t address = atom->getSectionOffset()+ref->getFixUpOffset();
 
2701         macho_relocation_info<P> reloc1;
 
2702         macho_relocation_info<P> reloc2;
 
2703         macho_scattered_relocation_info<P>* sreloc1 = (macho_scattered_relocation_info<P>*)&reloc1;
 
2704         macho_scattered_relocation_info<P>* sreloc2 = (macho_scattered_relocation_info<P>*)&reloc2;
 
2705         typename A::ReferenceKinds kind = (typename A::ReferenceKinds)ref->getKind();
 
2713                 case A::kPointerWeakImport:
 
2714                         if ( !isExtern && (ref->getTargetOffset() >= target.getSize()) ) {
 
2715                                 // use scattered reloc is target offset is outside target
 
2716                                 sreloc1->set_r_scattered(true);
 
2717                                 sreloc1->set_r_pcrel(false);
 
2718                                 sreloc1->set_r_length(getRelocPointerSize());
 
2719                                 sreloc1->set_r_type(GENERIC_RELOC_VANILLA);
 
2720                                 sreloc1->set_r_address(address);
 
2721                                 sreloc1->set_r_value(target.getAddress());
 
2724                                 reloc1.set_r_address(address);
 
2726                                         reloc1.set_r_symbolnum(symbolIndex);
 
2728                                         reloc1.set_r_symbolnum(sectionNum);
 
2729                                 reloc1.set_r_pcrel(false);
 
2730                                 reloc1.set_r_length(getRelocPointerSize());
 
2731                                 reloc1.set_r_extern(isExtern);
 
2732                                 reloc1.set_r_type(GENERIC_RELOC_VANILLA);
 
2734                         fSectionRelocs.push_back(reloc1);
 
2737                 case A::kPointerDiff16:
 
2738                 case A::kPointerDiff32:
 
2739                 case A::kPointerDiff64:
 
2741                                 pint_t toAddr = target.getAddress() + ref->getTargetOffset();
 
2742                                 pint_t fromAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
 
2743                                 sreloc1->set_r_scattered(true);
 
2744                                 sreloc1->set_r_pcrel(false);
 
2745                                 sreloc1->set_r_length( (kind == A::kPointerDiff32) ? 2 : ((kind == A::kPointerDiff64) ? 3 : 1));
 
2746                                 sreloc1->set_r_type(ref->getTargetOffset() != 0 ? PPC_RELOC_LOCAL_SECTDIFF : PPC_RELOC_SECTDIFF);
 
2747                                 sreloc1->set_r_address(address);
 
2748                                 sreloc1->set_r_value(toAddr);
 
2749                                 sreloc2->set_r_scattered(true);
 
2750                                 sreloc2->set_r_pcrel(false);
 
2751                                 sreloc1->set_r_length( (kind == A::kPointerDiff32) ? 2 : ((kind == A::kPointerDiff64) ? 3 : 1));
 
2752                                 sreloc2->set_r_type(PPC_RELOC_PAIR);
 
2753                                 sreloc2->set_r_address(0);
 
2754                                 sreloc2->set_r_value(fromAddr);
 
2755                                 fSectionRelocs.push_back(reloc2);
 
2756                                 fSectionRelocs.push_back(reloc1);
 
2760                 case A::kBranch24WeakImport:
 
2762                 case A::kDtraceProbeSite:
 
2763                 case A::kDtraceIsEnabledSite:
 
2764                         if ( (ref->getTargetOffset() == 0) || isExtern ) {
 
2765                                 reloc1.set_r_address(address);
 
2767                                         reloc1.set_r_symbolnum(symbolIndex);
 
2769                                         reloc1.set_r_symbolnum(sectionNum);
 
2770                                 reloc1.set_r_pcrel(true);
 
2771                                 reloc1.set_r_length(2);
 
2772                                 reloc1.set_r_type(PPC_RELOC_BR24);
 
2773                                 reloc1.set_r_extern(isExtern);
 
2776                                 sreloc1->set_r_scattered(true);
 
2777                                 sreloc1->set_r_pcrel(true);
 
2778                                 sreloc1->set_r_length(2);
 
2779                                 sreloc1->set_r_type(PPC_RELOC_BR24);
 
2780                                 sreloc1->set_r_address(address);
 
2781                                 sreloc1->set_r_value(target.getAddress());
 
2783                         fSectionRelocs.push_back(reloc1);
 
2787                         if ( (ref->getTargetOffset() == 0) || isExtern ) {
 
2788                                 reloc1.set_r_address(address);
 
2790                                         reloc1.set_r_symbolnum(symbolIndex);
 
2792                                         reloc1.set_r_symbolnum(sectionNum);
 
2793                                 reloc1.set_r_pcrel(true);
 
2794                                 reloc1.set_r_length(2);
 
2795                                 reloc1.set_r_type(PPC_RELOC_BR14);
 
2796                                 reloc1.set_r_extern(isExtern);
 
2799                                 sreloc1->set_r_scattered(true);
 
2800                                 sreloc1->set_r_pcrel(true);
 
2801                                 sreloc1->set_r_length(2);
 
2802                                 sreloc1->set_r_type(PPC_RELOC_BR14);
 
2803                                 sreloc1->set_r_address(address);
 
2804                                 sreloc1->set_r_value(target.getAddress());
 
2806                         fSectionRelocs.push_back(reloc1);
 
2809                 case A::kPICBaseLow16:
 
2810                 case A::kPICBaseLow14:
 
2812                                 pint_t fromAddr = atom->getAddress() + ref->getFromTargetOffset();
 
2813                                 pint_t toAddr = target.getAddress() + ref->getTargetOffset();
 
2814                                 sreloc1->set_r_scattered(true);
 
2815                                 sreloc1->set_r_pcrel(false);
 
2816                                 sreloc1->set_r_length(2);
 
2817                                 sreloc1->set_r_type(kind == A::kPICBaseLow16 ? PPC_RELOC_LO16_SECTDIFF : PPC_RELOC_LO14_SECTDIFF);
 
2818                                 sreloc1->set_r_address(address);
 
2819                                 sreloc1->set_r_value(target.getAddress());
 
2820                                 sreloc2->set_r_scattered(true);
 
2821                                 sreloc2->set_r_pcrel(false);
 
2822                                 sreloc2->set_r_length(2);
 
2823                                 sreloc2->set_r_type(PPC_RELOC_PAIR);
 
2824                                 sreloc2->set_r_address(((toAddr-fromAddr) >> 16) & 0xFFFF);
 
2825                                 sreloc2->set_r_value(fromAddr);
 
2826                                 fSectionRelocs.push_back(reloc2);
 
2827                                 fSectionRelocs.push_back(reloc1);
 
2831                 case A::kPICBaseHigh16:
 
2833                                 pint_t fromAddr = atom->getAddress() + ref->getFromTargetOffset();
 
2834                                 pint_t toAddr = target.getAddress() + ref->getTargetOffset();
 
2835                                 sreloc1->set_r_scattered(true);
 
2836                                 sreloc1->set_r_pcrel(false);
 
2837                                 sreloc1->set_r_length(2);
 
2838                                 sreloc1->set_r_type(PPC_RELOC_HA16_SECTDIFF);
 
2839                                 sreloc1->set_r_address(address);
 
2840                                 sreloc1->set_r_value(target.getAddress());
 
2841                                 sreloc2->set_r_scattered(true);
 
2842                                 sreloc2->set_r_pcrel(false);
 
2843                                 sreloc2->set_r_length(2);
 
2844                                 sreloc2->set_r_type(PPC_RELOC_PAIR);
 
2845                                 sreloc2->set_r_address((toAddr-fromAddr) & 0xFFFF);
 
2846                                 sreloc2->set_r_value(fromAddr);
 
2847                                 fSectionRelocs.push_back(reloc2);
 
2848                                 fSectionRelocs.push_back(reloc1);
 
2855                                 pint_t toAddr = target.getAddress() + ref->getTargetOffset();
 
2856                                 if ( (ref->getTargetOffset() == 0) || isExtern ) {
 
2857                                         reloc1.set_r_address(address);
 
2859                                                 reloc1.set_r_symbolnum(symbolIndex);
 
2861                                                 reloc1.set_r_symbolnum(sectionNum);
 
2862                                         reloc1.set_r_pcrel(false);
 
2863                                         reloc1.set_r_length(2);
 
2864                                         reloc1.set_r_extern(isExtern);
 
2865                                         reloc1.set_r_type(kind==A::kAbsLow16 ? PPC_RELOC_LO16 : PPC_RELOC_LO14);
 
2868                                         sreloc1->set_r_scattered(true);
 
2869                                         sreloc1->set_r_pcrel(false);
 
2870                                         sreloc1->set_r_length(2);
 
2871                                         sreloc1->set_r_type(kind==A::kAbsLow16 ? PPC_RELOC_LO16 : PPC_RELOC_LO14);
 
2872                                         sreloc1->set_r_address(address);
 
2873                                         sreloc1->set_r_value(target.getAddress());
 
2876                                         reloc2.set_r_address(ref->getTargetOffset() >> 16);
 
2878                                         reloc2.set_r_address(toAddr >> 16);
 
2879                                 reloc2.set_r_symbolnum(0);
 
2880                                 reloc2.set_r_pcrel(false);
 
2881                                 reloc2.set_r_length(2);
 
2882                                 reloc2.set_r_extern(false);
 
2883                                 reloc2.set_r_type(PPC_RELOC_PAIR);
 
2884                                 fSectionRelocs.push_back(reloc2);
 
2885                                 fSectionRelocs.push_back(reloc1);
 
2891                                 pint_t toAddr = target.getAddress() + ref->getTargetOffset();
 
2892                                 if ( (ref->getTargetOffset() == 0) || isExtern ) {
 
2893                                         reloc1.set_r_address(address);
 
2895                                                 reloc1.set_r_symbolnum(symbolIndex);
 
2897                                                 reloc1.set_r_symbolnum(sectionNum);
 
2898                                         reloc1.set_r_pcrel(false);
 
2899                                         reloc1.set_r_length(2);
 
2900                                         reloc1.set_r_extern(isExtern);
 
2901                                         reloc1.set_r_type(PPC_RELOC_HI16);
 
2904                                         sreloc1->set_r_scattered(true);
 
2905                                         sreloc1->set_r_pcrel(false);
 
2906                                         sreloc1->set_r_length(2);
 
2907                                         sreloc1->set_r_type(PPC_RELOC_HI16);
 
2908                                         sreloc1->set_r_address(address);
 
2909                                         sreloc1->set_r_value(target.getAddress());
 
2912                                         reloc2.set_r_address(ref->getTargetOffset() & 0xFFFF);
 
2914                                         reloc2.set_r_address(toAddr & 0xFFFF);
 
2915                                 reloc2.set_r_symbolnum(0);
 
2916                                 reloc2.set_r_pcrel(false);
 
2917                                 reloc2.set_r_length(2);
 
2918                                 reloc2.set_r_extern(false);
 
2919                                 reloc2.set_r_type(PPC_RELOC_PAIR);
 
2920                                 fSectionRelocs.push_back(reloc2);
 
2921                                 fSectionRelocs.push_back(reloc1);
 
2925                 case A::kAbsHigh16AddLow:
 
2927                                 pint_t toAddr = target.getAddress() + ref->getTargetOffset();
 
2928                                 uint32_t overflow = 0;
 
2929                                 if ( (toAddr & 0x00008000) != 0 )
 
2931                                 if ( (ref->getTargetOffset() == 0) || isExtern ) {
 
2932                                         reloc1.set_r_address(address);
 
2934                                                 reloc1.set_r_symbolnum(symbolIndex);
 
2936                                                 reloc1.set_r_symbolnum(sectionNum);
 
2937                                         reloc1.set_r_pcrel(false);
 
2938                                         reloc1.set_r_length(2);
 
2939                                         reloc1.set_r_extern(isExtern);
 
2940                                         reloc1.set_r_type(PPC_RELOC_HA16);
 
2943                                         sreloc1->set_r_scattered(true);
 
2944                                         sreloc1->set_r_pcrel(false);
 
2945                                         sreloc1->set_r_length(2);
 
2946                                         sreloc1->set_r_type(PPC_RELOC_HA16);
 
2947                                         sreloc1->set_r_address(address);
 
2948                                         sreloc1->set_r_value(target.getAddress());
 
2951                                         reloc2.set_r_address(ref->getTargetOffset() & 0xFFFF);
 
2953                                         reloc2.set_r_address(toAddr & 0xFFFF);
 
2954                                 reloc2.set_r_symbolnum(0);
 
2955                                 reloc2.set_r_pcrel(false);
 
2956                                 reloc2.set_r_length(2);
 
2957                                 reloc2.set_r_extern(false);
 
2958                                 reloc2.set_r_type(PPC_RELOC_PAIR);
 
2959                                 fSectionRelocs.push_back(reloc2);
 
2960                                 fSectionRelocs.push_back(reloc1);
 
2964                 case A::kDtraceTypeReference:
 
2965                 case A::kDtraceProbe:
 
2966                         // generates no relocs
 
2975 // There are cases when an entry in the indirect symbol table is the magic value
 
2976 // INDIRECT_SYMBOL_LOCAL instead of being a symbol index.  When that happens
 
2977 // the content of the corresponding part of the __nl_symbol_pointer section
 
2978 // must also change. 
 
2980 template <typename A>
 
2981 bool Writer<A>::indirectSymbolIsLocal(const ObjectFile::Reference* ref) const
 
2983         //  use INDIRECT_SYMBOL_LOCAL in non-lazy-pointers for atoms that won't be in symbol table or have an addend
 
2984         return ( !this->shouldExport(ref->getTarget()) || (ref->getTargetOffset() != 0) );
 
2988 template <typename A>
 
2989 void Writer<A>::buildObjectFileFixups()
 
2991         uint32_t relocIndex = 0;
 
2992         std::vector<SegmentInfo*>& segmentInfos = fSegmentInfos;
 
2993         const int segCount = segmentInfos.size();
 
2994         for(int i=0; i < segCount; ++i) {
 
2995                 SegmentInfo* curSegment = segmentInfos[i];
 
2996                 std::vector<SectionInfo*>& sectionInfos = curSegment->fSections;
 
2997                 const int sectionCount = sectionInfos.size();
 
2998                 for(int j=0; j < sectionCount; ++j) {
 
2999                         SectionInfo* curSection = sectionInfos[j];
 
3000                         //fprintf(stderr, "buildObjectFileFixups(): starting section %s\n", curSection->fSectionName);
 
3001                         std::vector<ObjectFile::Atom*>& sectionAtoms = curSection->fAtoms;
 
3002                         if ( ! curSection->fAllZeroFill ) {
 
3003                                 if ( curSection->fAllNonLazyPointers || curSection->fAllLazyPointers || curSection->fAllStubs )
 
3004                                         curSection->fIndirectSymbolOffset = fIndirectTableAtom->fTable.size();
 
3005                                 curSection->fRelocOffset = relocIndex;
 
3006                                 const int atomCount = sectionAtoms.size();
 
3007                                 for (int k=0; k < atomCount; ++k) {
 
3008                                         ObjectFile::Atom* atom = sectionAtoms[k];
 
3009                                         //fprintf(stderr, "buildObjectFileFixups(): atom %s\n", atom->getDisplayName());
 
3010                                         std::vector<ObjectFile::Reference*>& refs = atom->getReferences();
 
3011                                         const int refCount = refs.size();
 
3012                                         for (int l=0; l < refCount; ++l) {
 
3013                                                 ObjectFile::Reference* ref = refs[l];
 
3014                                                 if ( curSection->fAllNonLazyPointers || curSection->fAllLazyPointers || curSection->fAllStubs ) {
 
3015                                                         uint32_t offsetInSection = atom->getSectionOffset();
 
3016                                                         uint32_t indexInSection = offsetInSection / atom->getSize();
 
3017                                                         uint32_t undefinedSymbolIndex;
 
3018                                                         if ( curSection->fAllStubs ) {
 
3019                                                                 ObjectFile::Atom& stubTarget =ref->getTarget();
 
3020                                                                 ObjectFile::Atom& stubTargetTarget = stubTarget.getReferences()[0]->getTarget();
 
3021                                                                 undefinedSymbolIndex = this->symbolIndex(stubTargetTarget);
 
3022                                                                 //fprintf(stderr, "stub %s ==> %s ==> %s ==> index:%u\n", atom->getDisplayName(), stubTarget.getDisplayName(), stubTargetTarget.getDisplayName(), undefinedSymbolIndex);
 
3024                                                         else if ( curSection->fAllNonLazyPointers) {
 
3025                                                                 // only use INDIRECT_SYMBOL_LOCAL in non-lazy-pointers for atoms that won't be in symbol table or have an addend
 
3026                                                                 if ( this->indirectSymbolIsLocal(ref) )
 
3027                                                                         undefinedSymbolIndex = INDIRECT_SYMBOL_LOCAL;
 
3029                                                                         undefinedSymbolIndex = this->symbolIndex(ref->getTarget());
 
3032                                                                 // should never get here, fAllLazyPointers not used in generated .o files
 
3033                                                                 undefinedSymbolIndex = INDIRECT_SYMBOL_LOCAL;
 
3035                                                         uint32_t indirectTableIndex = indexInSection + curSection->fIndirectSymbolOffset;
 
3036                                                         IndirectEntry entry = { indirectTableIndex, undefinedSymbolIndex };
 
3037                                                         //printf("fIndirectTableAtom->fTable.add(sectionIndex=%u, indirectTableIndex=%u => %u), size=%lld\n", indexInSection, indirectTableIndex, undefinedSymbolIndex, atom->getSize());
 
3038                                                         fIndirectTableAtom->fTable.push_back(entry);
 
3039                                                         if ( curSection->fAllLazyPointers ) {
 
3040                                                                 ObjectFile::Atom& target = ref->getTarget();
 
3041                                                                 ObjectFile::Atom& fromTarget = ref->getFromTarget();
 
3042                                                                 if ( &fromTarget == NULL ) {
 
3043                                                                         fprintf(stderr, "lazy pointer %s missing initial binding\n", atom->getDisplayName());
 
3046                                                                         bool isExtern = ( ((target.getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
 
3047                                                                                 || (target.getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition))
 
3048                                                                                 && (target.getSymbolTableInclusion() != ObjectFile::Atom::kSymbolTableNotIn) );
 
3049                                                                         macho_relocation_info<P> reloc1;
 
3050                                                                         reloc1.set_r_address(atom->getSectionOffset());
 
3051                                                                         reloc1.set_r_symbolnum(isExtern ? this->symbolIndex(target) : target.getSection()->getIndex());
 
3052                                                                         reloc1.set_r_pcrel(false);
 
3053                                                                         reloc1.set_r_length();
 
3054                                                                         reloc1.set_r_extern(isExtern);
 
3055                                                                         reloc1.set_r_type(GENERIC_RELOC_VANILLA);
 
3056                                                                         fSectionRelocs.push_back(reloc1);
 
3060                                                         else if ( curSection->fAllStubs ) {
 
3061                                                                 relocIndex += this->addObjectRelocs(atom, ref);
 
3064                                                 else if ( (ref->getKind() != A::kNoFixUp) && (ref->getTargetBinding() != ObjectFile::Reference::kDontBind) ) {
 
3065                                                         relocIndex += this->addObjectRelocs(atom, ref);
 
3069                                 curSection->fRelocCount = relocIndex - curSection->fRelocOffset;
 
3074         // reverse the relocs
 
3075         std::reverse(fSectionRelocs.begin(), fSectionRelocs.end());
 
3077         // now reverse section reloc offsets
 
3078         for(int i=0; i < segCount; ++i) {
 
3079                 SegmentInfo* curSegment = segmentInfos[i];
 
3080                 std::vector<SectionInfo*>& sectionInfos = curSegment->fSections;
 
3081                 const int sectionCount = sectionInfos.size();
 
3082                 for(int j=0; j < sectionCount; ++j) {
 
3083                         SectionInfo* curSection = sectionInfos[j];
 
3084                         curSection->fRelocOffset = relocIndex - curSection->fRelocOffset - curSection->fRelocCount;
 
3091 bool Writer<ppc>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref)
 
3093         switch ( ref.getKind() ) {
 
3094                 case ppc::kAbsLow16:
 
3095                 case ppc::kAbsLow14:
 
3096                 case ppc::kAbsHigh16:
 
3097                 case ppc::kAbsHigh16AddLow:
 
3106 bool Writer<ppc64>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref)
 
3108         switch ( ref.getKind() ) {
 
3109                 case ppc::kAbsLow16:
 
3110                 case ppc::kAbsLow14:
 
3111                 case ppc::kAbsHigh16:
 
3112                 case ppc::kAbsHigh16AddLow:
 
3120 bool Writer<x86>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref)
 
3122         if ( ref.getKind() == x86::kAbsolute32 ) {
 
3123                 switch ( ref.getTarget().getDefinitionKind() ) {
 
3124                         case ObjectFile::Atom::kTentativeDefinition:
 
3125                         case ObjectFile::Atom::kRegularDefinition:
 
3126                         case ObjectFile::Atom::kWeakDefinition:
 
3127                                 // illegal in dylibs/bundles, until we support TEXT relocs 
 
3129                         case ObjectFile::Atom::kExternalDefinition:
 
3130                         case ObjectFile::Atom::kExternalWeakDefinition:
 
3131                                 // illegal until we support TEXT relocs
 
3133                         case ObjectFile::Atom::kAbsoluteSymbol:
 
3134                                 // absolute symbbols only allowed in static executables
 
3135                                 return ( fOptions.outputKind() != Options::kStaticExecutable);
 
3142 bool Writer<x86_64>::illegalRelocInFinalLinkedImage(const ObjectFile::Reference& ref)
 
3148 template <typename A>
 
3149 typename Writer<A>::RelocKind Writer<A>::relocationNeededInFinalLinkedImage(const ObjectFile::Atom& target) const
 
3151         switch ( target.getDefinitionKind() ) {
 
3152                 case ObjectFile::Atom::kTentativeDefinition:
 
3153                 case ObjectFile::Atom::kRegularDefinition:
 
3154                         // in main executables, the only way regular symbols are indirected is if -interposable is used
 
3155                         if ( fOptions.outputKind() == Options::kDynamicExecutable ) {
 
3156                                 if ( this->shouldExport(target) && fOptions.interposable() )
 
3157                                         return kRelocExternal;
 
3158                                 else if ( fSlideable )
 
3159                                         return kRelocInternal;
 
3163                         // for flat-namespace or interposable two-level-namespace
 
3164                         // all references to exported symbols get indirected
 
3165                         else if ( this->shouldExport(target) &&
 
3166                            ((fOptions.nameSpace() == Options::kFlatNameSpace)
 
3167                           || (fOptions.nameSpace() == Options::kForceFlatNameSpace)
 
3168                           || fOptions.interposable()) 
 
3169                           && (target.getName() != NULL) 
 
3170                           && (strncmp(target.getName(), ".objc_class_", 12) != 0) ) // <rdar://problem/5254468>
 
3171                                 return kRelocExternal;
 
3172                         else if ( fSlideable )
 
3173                                 return kRelocInternal;
 
3176                 case ObjectFile::Atom::kWeakDefinition:
 
3177                         // all calls to global weak definitions get indirected
 
3178                         if ( this->shouldExport(target) )
 
3179                                 return kRelocExternal;
 
3180                         else if ( fSlideable )
 
3181                                 return kRelocInternal;
 
3184                 case ObjectFile::Atom::kExternalDefinition:
 
3185                 case ObjectFile::Atom::kExternalWeakDefinition:
 
3186                         return kRelocExternal;
 
3187                 case ObjectFile::Atom::kAbsoluteSymbol:
 
3193 template <typename A>
 
3194 uint64_t Writer<A>::relocAddressInFinalLinkedImage(uint64_t address, const ObjectFile::Atom* atom) const
 
3196         // for 32-bit architectures, the r_address field in relocs
 
3197         // for final linked images is the offset from the first segment
 
3198         uint64_t result = address - fSegmentInfos[0]->fBaseAddress;
 
3199         // or the offset from the first writable segment if built split-seg
 
3200         if ( fOptions.splitSeg() )
 
3201                 result = address - fFirstWritableSegment->fBaseAddress;
 
3202         if ( result > 0x7FFFFFFF ) {
 
3203                 throwf("image too large: address can't fit in 31-bit r_address field in %s from %s",
 
3204                         atom->getDisplayName(), atom->getFile()->getPath());
 
3210 uint64_t Writer<x86_64>::relocAddressInFinalLinkedImage(uint64_t address, const ObjectFile::Atom* atom)  const
 
3212         // for x86_64, the r_address field in relocs for final linked images 
 
3213         // is the offset from the start address of the first writable segment
 
3214         uint64_t result = address - fFirstWritableSegment->fBaseAddress;
 
3215         if ( result > 0xFFFFFFFF ) {
 
3216                 throwf("image too large: address can't fit in 32-bit r_address field in %s from %s",
 
3217                         atom->getDisplayName(), atom->getFile()->getPath());
 
3223 uint64_t Writer<ppc64>::relocAddressInFinalLinkedImage(uint64_t address, const ObjectFile::Atom* atom)  const
 
3225         // for ppc64, the Mac OS X 10.4 dyld assumes r_address is always the offset from the base address.  
 
3226         // the 10.5 dyld, iterprets the r_address as:
 
3227         //   1) an offset from the base address, iff there are no writable segments with a address > 4GB from base address, otherwise
 
3228         //   2) an offset from the base address of the first writable segment
 
3229         // For dyld, r_address is always the offset from the base address
 
3231         bool badFor10_4 = false;
 
3232         if ( fWritableSegmentPastFirst4GB ) {
 
3233                 if ( fOptions.macosxVersionMin() < ObjectFile::ReaderOptions::k10_5 )
 
3235                 result = address - fFirstWritableSegment->fBaseAddress;
 
3236                 if ( result > 0xFFFFFFFF ) {
 
3237                         throwf("image too large: address can't fit in 32-bit r_address field in %s from %s",
 
3238                                 atom->getDisplayName(), atom->getFile()->getPath());
 
3242                 result = address - fSegmentInfos[0]->fBaseAddress;
 
3243                 if ( (fOptions.macosxVersionMin() < ObjectFile::ReaderOptions::k10_5) && (result > 0x7FFFFFFF) )
 
3247                         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",
 
3248                                 atom->getDisplayName(), atom->getFile()->getPath());
 
3254 template <> bool    Writer<ppc>::preboundLazyPointerType(uint8_t* type) { *type = PPC_RELOC_PB_LA_PTR; return true; }
 
3255 template <> bool  Writer<ppc64>::preboundLazyPointerType(uint8_t* type) { throw "prebinding not supported"; }
 
3256 template <> bool    Writer<x86>::preboundLazyPointerType(uint8_t* type) { *type = GENERIC_RELOC_PB_LA_PTR; return true; }
 
3257 template <> bool Writer<x86_64>::preboundLazyPointerType(uint8_t* type) { throw "prebinding not supported"; }
 
3260 template <typename A>
 
3261 void Writer<A>::buildExecutableFixups()
 
3263         fIndirectTableAtom->fTable.reserve(50);  // minimize reallocations
 
3264         std::vector<SegmentInfo*>& segmentInfos = fSegmentInfos;
 
3265         const int segCount = segmentInfos.size();
 
3266         for(int i=0; i < segCount; ++i) {
 
3267                 SegmentInfo* curSegment = segmentInfos[i];
 
3268                 std::vector<SectionInfo*>& sectionInfos = curSegment->fSections;
 
3269                 const int sectionCount = sectionInfos.size();
 
3270                 for(int j=0; j < sectionCount; ++j) {
 
3271                         SectionInfo* curSection = sectionInfos[j];
 
3272                         //fprintf(stderr, "starting section %s\n", curSection->fSectionName);
 
3273                         std::vector<ObjectFile::Atom*>& sectionAtoms = curSection->fAtoms;
 
3274                         if ( ! curSection->fAllZeroFill ) {
 
3275                                 if ( curSection->fAllNonLazyPointers || curSection->fAllLazyPointers || curSection->fAllStubs || curSection->fAllSelfModifyingStubs )
 
3276                                         curSection->fIndirectSymbolOffset = fIndirectTableAtom->fTable.size();
 
3277                                 const int atomCount = sectionAtoms.size();
 
3278                                 for (int k=0; k < atomCount; ++k) {
 
3279                                         ObjectFile::Atom* atom = sectionAtoms[k];
 
3280                                         std::vector<ObjectFile::Reference*>& refs = atom->getReferences();
 
3281                                         const int refCount = refs.size();
 
3282                                         //fprintf(stderr, "atom %s has %d references in section %s, %p\n", atom->getDisplayName(), refCount, curSection->fSectionName, atom->getSection());
 
3283                                         for (int l=0; l < refCount; ++l) {
 
3284                                                 ObjectFile::Reference* ref = refs[l];
 
3285                                                 if ( curSection->fAllNonLazyPointers || curSection->fAllLazyPointers ) {
 
3286                                                         // if atom is in (non)lazy_pointer section, this is encoded as an indirect symbol
 
3287                                                         if ( atom->getSize() != sizeof(pint_t) ) {
 
3288                                                                 printf("wrong size pointer atom %s from file %s\n", atom->getDisplayName(), atom->getFile()->getPath());
 
3290                                                         ObjectFile::Atom* pointerTarget = &(ref->getTarget());
 
3291                                                         if ( curSection->fAllLazyPointers ) {
 
3292                                                                 pointerTarget = ((LazyPointerAtom<A>*)atom)->getTarget();
 
3294                                                         uint32_t offsetInSection = atom->getSectionOffset();
 
3295                                                         uint32_t indexInSection = offsetInSection / sizeof(pint_t);
 
3296                                                         uint32_t undefinedSymbolIndex = INDIRECT_SYMBOL_LOCAL;
 
3297                                                         if ( this->relocationNeededInFinalLinkedImage(*pointerTarget) == kRelocExternal )
 
3298                                                                 undefinedSymbolIndex = this->symbolIndex(*pointerTarget);
 
3299                                                         uint32_t indirectTableIndex = indexInSection + curSection->fIndirectSymbolOffset;
 
3300                                                         IndirectEntry entry = { indirectTableIndex, undefinedSymbolIndex };
 
3301                                                         //fprintf(stderr,"fIndirectTableAtom->fTable.add(%d-%d => 0x%X-%s), size=%lld\n", indexInSection, indirectTableIndex, undefinedSymbolIndex, ref->getTarget().getName(), atom->getSize());
 
3302                                                         fIndirectTableAtom->fTable.push_back(entry);
 
3303                                                         if ( curSection->fAllLazyPointers ) {
 
3304                                                                 uint8_t preboundLazyType;
 
3305                                                                 if ( fOptions.prebind() && (fDyldHelper != NULL) && preboundLazyPointerType(&preboundLazyType) ) {
 
3306                                                                         // this is a prebound image, need special relocs for dyld to reset lazy pointers if prebinding is invalid
 
3307                                                                         macho_scattered_relocation_info<P> pblaReloc;
 
3308                                                                         pblaReloc.set_r_scattered(true);
 
3309                                                                         pblaReloc.set_r_pcrel(false);
 
3310                                                                         pblaReloc.set_r_length();
 
3311                                                                         pblaReloc.set_r_type(preboundLazyType);
 
3312                                                                         pblaReloc.set_r_address(relocAddressInFinalLinkedImage(atom->getAddress(), atom));
 
3313                                                                         pblaReloc.set_r_value(fDyldHelper->getAddress());
 
3314                                                                         fInternalRelocs.push_back(*((macho_relocation_info<P>*)&pblaReloc));
 
3316                                                                 else if ( fSlideable ) {
 
3317                                                                         // this is a non-prebound dylib/bundle, need vanilla internal relocation to fix up binding handler if image slides
 
3318                                                                         macho_relocation_info<P> dyldHelperReloc;
 
3319                                                                         uint32_t sectionNum = 1;
 
3320                                                                         if ( fDyldHelper != NULL )
 
3321                                                                                 sectionNum = ((SectionInfo*)(fDyldHelper->getSection()))->getIndex();
 
3322                                                                         //fprintf(stderr, "lazy pointer reloc, section index=%u, section name=%s\n", sectionNum, curSection->fSectionName);
 
3323                                                                         dyldHelperReloc.set_r_address(relocAddressInFinalLinkedImage(atom->getAddress(), atom));
 
3324                                                                         dyldHelperReloc.set_r_symbolnum(sectionNum);
 
3325                                                                         dyldHelperReloc.set_r_pcrel(false);
 
3326                                                                         dyldHelperReloc.set_r_length();
 
3327                                                                         dyldHelperReloc.set_r_extern(false);
 
3328                                                                         dyldHelperReloc.set_r_type(GENERIC_RELOC_VANILLA);
 
3329                                                                         fInternalRelocs.push_back(dyldHelperReloc);
 
3333                                                 else if ( (ref->getKind() == A::kPointer) || (ref->getKind() == A::kPointerWeakImport) ) {
 
3334                                                         if ( fSlideable && ((curSegment->fInitProtection & VM_PROT_WRITE) == 0) ) {
 
3335                                                                 throwf("pointer in read-only segment not allowed in slidable image, used in %s from %s",
 
3336                                                                                 atom->getDisplayName(), atom->getFile()->getPath());
 
3338                                                         switch ( this->relocationNeededInFinalLinkedImage(ref->getTarget()) ) {
 
3342                                                                 case kRelocInternal:
 
3344                                                                                 macho_relocation_info<P> internalReloc;
 
3345                                                                                 SectionInfo* sectInfo = (SectionInfo*)ref->getTarget().getSection();
 
3346                                                                                 uint32_t sectionNum = sectInfo->getIndex();
 
3347                                                                                 // special case _mh_dylib_header and friends which are not in any real section
 
3348                                                                                 if ( (sectionNum ==0) && sectInfo->fVirtualSection && (strcmp(sectInfo->fSectionName, "._mach_header") == 0) )
 
3350                                                                                 internalReloc.set_r_address(this->relocAddressInFinalLinkedImage(atom->getAddress() + ref->getFixUpOffset(), atom));
 
3351                                                                                 internalReloc.set_r_symbolnum(sectionNum);
 
3352                                                                                 internalReloc.set_r_pcrel(false);
 
3353                                                                                 internalReloc.set_r_length();
 
3354                                                                                 internalReloc.set_r_extern(false);
 
3355                                                                                 internalReloc.set_r_type(GENERIC_RELOC_VANILLA);
 
3356                                                                                 fInternalRelocs.push_back(internalReloc);
 
3359                                                                 case kRelocExternal:
 
3361                                                                                 macho_relocation_info<P> externalReloc;
 
3362                                                                                 externalReloc.set_r_address(this->relocAddressInFinalLinkedImage(atom->getAddress() + ref->getFixUpOffset(), atom));
 
3363                                                                                 externalReloc.set_r_symbolnum(this->symbolIndex(ref->getTarget()));
 
3364                                                                                 externalReloc.set_r_pcrel(false);
 
3365                                                                                 externalReloc.set_r_length();
 
3366                                                                                 externalReloc.set_r_extern(true);
 
3367                                                                                 externalReloc.set_r_type(GENERIC_RELOC_VANILLA);
 
3368                                                                                 fExternalRelocs.push_back(externalReloc);
 
3373                                                 else if ( this->illegalRelocInFinalLinkedImage(*ref) ) {
 
3374                                                         throwf("absolute addressing (perhaps -mdynamic-no-pic) used in %s from %s not allowed in slidable image", atom->getDisplayName(), atom->getFile()->getPath());
 
3377                                         if ( curSection->fAllSelfModifyingStubs || curSection->fAllStubs ) {
 
3378                                                 ObjectFile::Atom* stubTarget = ((StubAtom<A>*)atom)->getTarget();
 
3379                                                 uint32_t undefinedSymbolIndex = (stubTarget != NULL) ? this->symbolIndex(*stubTarget) : INDIRECT_SYMBOL_ABS;
 
3380                                                 uint32_t offsetInSection = atom->getSectionOffset();
 
3381                                                 uint32_t indexInSection = offsetInSection / atom->getSize();
 
3382                                                 uint32_t indirectTableIndex = indexInSection + curSection->fIndirectSymbolOffset;
 
3383                                                 IndirectEntry entry = { indirectTableIndex, undefinedSymbolIndex };
 
3384                                                 //fprintf(stderr,"for stub: fIndirectTableAtom->fTable.add(%d-%d => 0x%X-%s), size=%lld\n", indexInSection, indirectTableIndex, undefinedSymbolIndex, stubTarget->getName(), atom->getSize());
 
3385                                                 fIndirectTableAtom->fTable.push_back(entry);
 
3391         if ( fSplitCodeToDataContentAtom != NULL )
 
3392                 fSplitCodeToDataContentAtom->encode();
 
3397 void Writer<ppc>::addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref)
 
3399         switch ( (ppc::ReferenceKinds)ref->getKind() ) {
 
3400                 case ppc::kPICBaseHigh16:
 
3401                         fSplitCodeToDataContentAtom->addPPCHi16Location(atom, ref->getFixUpOffset());
 
3403                 case ppc::kPointerDiff32:
 
3404                         fSplitCodeToDataContentAtom->add32bitPointerLocation(atom, ref->getFixUpOffset());
 
3406                 case ppc::kPointerDiff64:
 
3407                         fSplitCodeToDataContentAtom->add64bitPointerLocation(atom, ref->getFixUpOffset());
 
3411                 case ppc::kPointerWeakImport:
 
3412                 case ppc::kPICBaseLow16:
 
3413                 case ppc::kPICBaseLow14:
 
3417                         fprintf(stderr, "ld: warning codegen with reference kind %d in %s prevents image from loading in dyld shared cache\n", ref->getKind(), atom->getDisplayName());
 
3418                         fSplitCodeToDataContentAtom->setCantEncode();
 
3423 void Writer<ppc64>::addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref)
 
3425         switch ( (ppc64::ReferenceKinds)ref->getKind()  ) {
 
3426                 case ppc64::kPICBaseHigh16:
 
3427                         fSplitCodeToDataContentAtom->addPPCHi16Location(atom, ref->getFixUpOffset());
 
3429                 case ppc64::kPointerDiff32:
 
3430                         fSplitCodeToDataContentAtom->add32bitPointerLocation(atom, ref->getFixUpOffset());
 
3432                 case ppc64::kPointerDiff64:
 
3433                         fSplitCodeToDataContentAtom->add64bitPointerLocation(atom, ref->getFixUpOffset());
 
3435                 case ppc64::kNoFixUp:
 
3436                 case ppc64::kPointer:
 
3437                 case ppc64::kPointerWeakImport:
 
3438                 case ppc64::kPICBaseLow16:
 
3439                 case ppc64::kPICBaseLow14:
 
3443                         fprintf(stderr, "ld: warning codegen with reference kind %d in %s prevents image from loading in dyld shared cache\n", ref->getKind(), atom->getDisplayName());
 
3444                         fSplitCodeToDataContentAtom->setCantEncode();
 
3449 void Writer<x86>::addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref)
 
3451         switch ( (x86::ReferenceKinds)ref->getKind()  ) {
 
3452                 case x86::kPointerDiff:
 
3453                         if ( strcmp(ref->getTarget().getSegment().getName(), "__IMPORT") == 0 ) 
 
3454                                 fSplitCodeToDataContentAtom->add32bitImportLocation(atom, ref->getFixUpOffset());
 
3456                                 fSplitCodeToDataContentAtom->add32bitPointerLocation(atom, ref->getFixUpOffset());
 
3460                 case x86::kPointerWeakImport:
 
3464                 case x86::kPCRel32WeakImport:
 
3465                         if (    (&(ref->getTarget().getSegment()) == &Segment::fgImportSegment)
 
3466                                 ||  (&(ref->getTarget().getSegment()) == &Segment::fgROImportSegment) ) {
 
3467                                 fSplitCodeToDataContentAtom->add32bitImportLocation(atom, ref->getFixUpOffset());
 
3470                         // fall into warning case
 
3472                         fprintf(stderr, "ld: warning codegen in %s (offset 0x%08llX) prevents image from loading in dyld shared cache\n", atom->getDisplayName(), ref->getFixUpOffset());
 
3473                         fSplitCodeToDataContentAtom->setCantEncode();
 
3478 void Writer<x86_64>::addCrossSegmentRef(const ObjectFile::Atom* atom, const ObjectFile::Reference* ref)
 
3480         switch ( (x86_64::ReferenceKinds)ref->getKind()  ) {
 
3481                 case x86_64::kPCRel32:
 
3482                 case x86_64::kPCRel32_1:
 
3483                 case x86_64::kPCRel32_2:
 
3484                 case x86_64::kPCRel32_4:
 
3485                 case x86_64::kPCRel32GOTLoad:
 
3486                 case x86_64::kPCRel32GOTLoadWeakImport:
 
3487                 case x86_64::kPCRel32GOT:
 
3488                 case x86_64::kPCRel32GOTWeakImport:
 
3489                 case x86_64::kPointerDiff32:
 
3490                         fSplitCodeToDataContentAtom->add32bitPointerLocation(atom, ref->getFixUpOffset());
 
3492                 case x86_64::kPointerDiff:
 
3493                         fSplitCodeToDataContentAtom->add64bitPointerLocation(atom, ref->getFixUpOffset());
 
3495                 case x86_64::kNoFixUp:
 
3496                 case x86_64::kPointer:
 
3500                         fprintf(stderr, "ld: warning codegen in %s with kind %d prevents image from loading in dyld shared cache\n", atom->getDisplayName(), ref->getKind());
 
3501                         fSplitCodeToDataContentAtom->setCantEncode();
 
3506 template <typename A>
 
3507 bool Writer<A>::segmentsCanSplitApart(const ObjectFile::Atom& from, const ObjectFile::Atom& to)
 
3509         switch ( to.getDefinitionKind() ) {
 
3510                 case ObjectFile::Atom::kExternalDefinition:
 
3511                 case ObjectFile::Atom::kExternalWeakDefinition:
 
3512                 case ObjectFile::Atom::kAbsoluteSymbol:
 
3514                 case ObjectFile::Atom::kRegularDefinition:
 
3515                 case ObjectFile::Atom::kWeakDefinition:
 
3516                 case ObjectFile::Atom::kTentativeDefinition:
 
3517                         // segments with same permissions slide together
 
3518                         return ( (from.getSegment().isContentExecutable() != to.getSegment().isContentExecutable())
 
3519                                         || (from.getSegment().isContentWritable() != to.getSegment().isContentWritable()) );
 
3521         throw "ld64 internal error";
 
3526 void Writer<ppc>::writeNoOps(uint32_t from, uint32_t to)
 
3529         OSWriteBigInt32(&ppcNop, 0, 0x60000000);
 
3530         for (uint32_t p=from; p < to; p += 4)
 
3531                 ::pwrite(fFileDescriptor, &ppcNop, 4, p);
 
3535 void Writer<ppc64>::writeNoOps(uint32_t from, uint32_t to)
 
3538         OSWriteBigInt32(&ppcNop, 0, 0x60000000);
 
3539         for (uint32_t p=from; p < to; p += 4)
 
3540                 ::pwrite(fFileDescriptor, &ppcNop, 4, p);
 
3544 void Writer<x86>::writeNoOps(uint32_t from, uint32_t to)
 
3546         uint8_t x86Nop = 0x90;
 
3547         for (uint32_t p=from; p < to; ++p)
 
3548                 ::pwrite(fFileDescriptor, &x86Nop, 1, p);
 
3552 void Writer<x86_64>::writeNoOps(uint32_t from, uint32_t to)
 
3554         uint8_t x86Nop = 0x90;
 
3555         for (uint32_t p=from; p < to; ++p)
 
3556                 ::pwrite(fFileDescriptor, &x86Nop, 1, p);
 
3561 void Writer<ppc>::copyNoOps(uint8_t* from, uint8_t* to)
 
3563         for (uint8_t* p=from; p < to; p += 4)
 
3564                 OSWriteBigInt32((uint32_t*)p, 0, 0x60000000);
 
3568 void Writer<ppc64>::copyNoOps(uint8_t* from, uint8_t* to)
 
3570         for (uint8_t* p=from; p < to; p += 4)
 
3571                 OSWriteBigInt32((uint32_t*)p, 0, 0x60000000);
 
3575 void Writer<x86>::copyNoOps(uint8_t* from, uint8_t* to)
 
3577         for (uint8_t* p=from; p < to; ++p)
 
3582 void Writer<x86_64>::copyNoOps(uint8_t* from, uint8_t* to)
 
3584         for (uint8_t* p=from; p < to; ++p)
 
3589 static const char* stringName(const char* str)
 
3591         if ( strncmp(str, "cstring=", 8) == 0)  {
 
3592                 static char buffer[1024];
 
3595                 for(const char*s = &str[8]; *s != '\0'; ++s) {
 
3609                         if ( t > &buffer[1020] ) {
 
3628 template <> const char* Writer<ppc>::getArchString()    { return "ppc"; }
 
3629 template <> const char* Writer<ppc64>::getArchString()  { return "ppc64"; }
 
3630 template <> const char* Writer<x86>::getArchString()    { return "i386"; }
 
3631 template <> const char* Writer<x86_64>::getArchString() { return "x86_64"; }
 
3633 template <typename A>
 
3634 void Writer<A>::writeMap()
 
3636         if ( fOptions.generatedMapPath() != NULL ) {
 
3637                 FILE* mapFile = fopen(fOptions.generatedMapPath(), "w"); 
 
3638                 if ( mapFile != NULL ) {
 
3639                         // write output path
 
3640                         fprintf(mapFile, "# Path: %s\n", fFilePath);
 
3641                         // write output architecure
 
3642                         fprintf(mapFile, "# Arch: %s\n", getArchString());
 
3644                         if ( fUUIDAtom != NULL ) {
 
3645                                 const uint8_t* uuid = fUUIDAtom->getUUID();
 
3646                                 fprintf(mapFile, "# UUID: %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X \n",
 
3647                                         uuid[0], uuid[1], uuid[2],  uuid[3],  uuid[4],  uuid[5],  uuid[6],  uuid[7],
 
3648                                         uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
 
3650                         // write table of object files
 
3651                         std::map<ObjectFile::Reader*, uint32_t> readerToOrdinal;
 
3652                         std::map<uint32_t, ObjectFile::Reader*> ordinalToReader;
 
3653                         std::map<ObjectFile::Reader*, uint32_t> readerToFileOrdinal;
 
3654                         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
3655                                 std::vector<SectionInfo*>& sectionInfos = (*segit)->fSections;
 
3656                                 for (std::vector<SectionInfo*>::iterator secit = sectionInfos.begin(); secit != sectionInfos.end(); ++secit) {
 
3657                                         if ( ! (*secit)->fVirtualSection ) {
 
3658                                                 std::vector<ObjectFile::Atom*>& sectionAtoms = (*secit)->fAtoms;
 
3659                                                 for (std::vector<ObjectFile::Atom*>::iterator ait = sectionAtoms.begin(); ait != sectionAtoms.end(); ++ait) {
 
3660                                                         ObjectFile::Reader* reader = (*ait)->getFile();
 
3661                                                         uint32_t readerOrdinal = (*ait)->getOrdinal();
 
3662                                                         std::map<ObjectFile::Reader*, uint32_t>::iterator pos = readerToOrdinal.find(reader);
 
3663                                                         if ( pos == readerToOrdinal.end() ) {
 
3664                                                                 readerToOrdinal[reader] = readerOrdinal;
 
3665                                                                 ordinalToReader[readerOrdinal] = reader;
 
3671                         fprintf(mapFile, "# Object files:\n");
 
3672                         fprintf(mapFile, "[%3u] %s\n", 0, "linker synthesized");
 
3673                         uint32_t fileIndex = 0;
 
3674                         readerToFileOrdinal[this] = fileIndex++;
 
3675                         for(std::map<uint32_t, ObjectFile::Reader*>::iterator it = ordinalToReader.begin(); it != ordinalToReader.end(); ++it) {
 
3676                                 if ( it->first != 0 ) {
 
3677                                         fprintf(mapFile, "[%3u] %s\n", fileIndex, it->second->getPath());
 
3678                                         readerToFileOrdinal[it->second] = fileIndex++;
 
3681                         // write table of sections
 
3682                         fprintf(mapFile, "# Sections:\n");
 
3683                         fprintf(mapFile, "# Address\tSize    \tSegment\tSection\n"); 
 
3684                         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
3685                                 std::vector<SectionInfo*>& sectionInfos = (*segit)->fSections;
 
3686                                 for (std::vector<SectionInfo*>::iterator secit = sectionInfos.begin(); secit != sectionInfos.end(); ++secit) {
 
3687                                         if ( ! (*secit)->fVirtualSection ) {
 
3688                                                 SectionInfo* sect = *secit;
 
3689                                                 fprintf(mapFile, "0x%08llX\t0x%08llX\t%s\t%s\n", sect->getBaseAddress(), sect->fSize, 
 
3690                                                         (*segit)->fName, sect->fSectionName);
 
3694                         // write table of symbols
 
3695                         fprintf(mapFile, "# Symbols:\n");
 
3696                         fprintf(mapFile, "# Address\tSize    \tFile  Name\n"); 
 
3697                         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
3698                                 std::vector<SectionInfo*>& sectionInfos = (*segit)->fSections;
 
3699                                 for (std::vector<SectionInfo*>::iterator secit = sectionInfos.begin(); secit != sectionInfos.end(); ++secit) {
 
3700                                         if ( ! (*secit)->fVirtualSection ) {
 
3701                                                 std::vector<ObjectFile::Atom*>& sectionAtoms = (*secit)->fAtoms;
 
3702                                                 bool isCstring = (strcmp((*secit)->fSectionName, "__cstring") == 0);
 
3703                                                 for (std::vector<ObjectFile::Atom*>::iterator ait = sectionAtoms.begin(); ait != sectionAtoms.end(); ++ait) {
 
3704                                                         ObjectFile::Atom* atom = *ait;
 
3705                                                         fprintf(mapFile, "0x%08llX\t0x%08llX\t[%3u] %s\n", atom->getAddress(), atom->getSize(), 
 
3706                                                                 readerToFileOrdinal[atom->getFile()], isCstring ? stringName(atom->getDisplayName()): atom->getDisplayName());
 
3714                         fprintf(stderr, "ld: warning could not write map file: %s\n", fOptions.generatedMapPath());
 
3719 template <typename A>
 
3720 uint64_t Writer<A>::writeAtoms()
 
3722         // try to allocate buffer for entire output file content
 
3723         SectionInfo* lastSection = fSegmentInfos.back()->fSections.back();
 
3724         uint64_t fileBufferSize = (lastSection->fFileOffset + lastSection->fSize + 4095) & (-4096);
 
3725         uint8_t* wholeBuffer = (uint8_t*)calloc(fileBufferSize, 1);
 
3726         uint8_t* atomBuffer = NULL;
 
3727         bool streaming = false;
 
3728         if ( wholeBuffer == NULL ) {
 
3729                 atomBuffer = new uint8_t[(fLargestAtomSize+4095) & (-4096)];
 
3734         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
3735                 SegmentInfo* curSegment = *segit;
 
3736                 bool isTextSeg = (strcmp(curSegment->fName, "__TEXT") == 0);
 
3737                 std::vector<SectionInfo*>& sectionInfos = curSegment->fSections;
 
3738                 for (std::vector<SectionInfo*>::iterator secit = sectionInfos.begin(); secit != sectionInfos.end(); ++secit) {
 
3739                         SectionInfo* curSection = *secit;
 
3740                         std::vector<ObjectFile::Atom*>& sectionAtoms = curSection->fAtoms;
 
3741                         //printf("writing with max atom size 0x%X\n", fLargestAtomSize);
 
3742                         //fprintf(stderr, "writing %d atoms for section %s\n", (int)sectionAtoms.size(), curSection->fSectionName);
 
3743                         if ( ! curSection->fAllZeroFill ) {
 
3744                                 end = curSection->fFileOffset;
 
3745                                 bool needsNops = isTextSeg && (strcmp(curSection->fSectionName, "__cstring") != 0);
 
3746                                 for (std::vector<ObjectFile::Atom*>::iterator ait = sectionAtoms.begin(); ait != sectionAtoms.end(); ++ait) {
 
3747                                         ObjectFile::Atom* atom = *ait;
 
3748                                         if ( (atom->getDefinitionKind() != ObjectFile::Atom::kExternalDefinition)
 
3749                                           && (atom->getDefinitionKind() != ObjectFile::Atom::kExternalWeakDefinition)
 
3750                                           && (atom->getDefinitionKind() != ObjectFile::Atom::kAbsoluteSymbol) ) {
 
3751                                                 uint32_t fileOffset = curSection->fFileOffset + atom->getSectionOffset();
 
3752                                                 if ( fileOffset != end ) {
 
3754                                                                 // fill gaps with no-ops
 
3756                                                                         writeNoOps(end, fileOffset);
 
3758                                                                         copyNoOps(&wholeBuffer[end], &wholeBuffer[fileOffset]);
 
3760                                                         else if ( streaming ) {
 
3762                                                                 if ( (fileOffset-end) == 4 ) {
 
3764                                                                         ::pwrite(fFileDescriptor, &zero, 4, end);
 
3767                                                                         uint8_t zero = 0x00;
 
3768                                                                         for (uint32_t p=end; p < fileOffset; ++p)
 
3769                                                                                 ::pwrite(fFileDescriptor, &zero, 1, p);
 
3773                                                 uint64_t atomSize = atom->getSize();
 
3775                                                         if ( atomSize > fLargestAtomSize ) 
 
3776                                                                 throwf("ld64 internal error: atom \"%s\"is larger than expected 0x%X > 0x%llX", 
 
3777                                                                                         atom->getDisplayName(), atomSize, fLargestAtomSize);
 
3780                                                         if ( fileOffset > fileBufferSize )
 
3781                                                                 throwf("ld64 internal error: atom \"%s\" has file offset greater thatn expceted 0x%X > 0x%llX", 
 
3782                                                                                         atom->getDisplayName(), fileOffset, fileBufferSize);
 
3784                                                 uint8_t* buffer = streaming ? atomBuffer : &wholeBuffer[fileOffset];
 
3785                                                 end = fileOffset+atomSize;
 
3787                                                 atom->copyRawContent(buffer);
 
3788                                                 // apply any fix-ups
 
3790                                                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
3791                                                         for (std::vector<ObjectFile::Reference*>::iterator it=references.begin(); it != references.end(); it++) {
 
3792                                                                 ObjectFile::Reference* ref = *it;
 
3793                                                                 if ( fOptions.outputKind() == Options::kObjectFile ) {
 
3795                                                                         // skip fix-ups for undefined targets
 
3796                                                                         if ( &(ref->getTarget()) != NULL )
 
3797                                                                                 this->fixUpReferenceRelocatable(ref, atom, buffer);
 
3800                                                                         // producing final linked image
 
3801                                                                         this->fixUpReferenceFinal(ref, atom, buffer);
 
3805                                                 catch (const char* msg) {
 
3806                                                         throwf("%s in %s from %s", msg, atom->getDisplayName(), atom->getFile()->getPath());
 
3808                                                 //fprintf(stderr, "writing 0x%08X -> 0x%08X (addr=0x%llX, size=0x%llX), atom %s from %s\n", 
 
3809                                                 //      fileOffset, end, atom->getAddress(), atom->getSize(), atom->getDisplayName(), atom->getFile()->getPath());
 
3812                                                         ::pwrite(fFileDescriptor, buffer, atomSize, fileOffset);
 
3815                                                         if ( (fileOffset + atomSize) > size )
 
3816                                                                 size = fileOffset + atomSize;
 
3824         // update content based UUID
 
3825         if ( fOptions.getUUIDMode() == Options::kUUIDContent ) {
 
3826                 uint8_t digest[CC_MD5_DIGEST_LENGTH];
 
3828                         // if output file file did not fit in memory, re-read file to generate md5 hash
 
3829                         uint32_t kMD5BufferSize = 16*1024;
 
3830                         uint8_t* md5Buffer = (uint8_t*)::malloc(kMD5BufferSize);
 
3831                         if ( md5Buffer != NULL ) {
 
3832                                 CC_MD5_CTX md5State;
 
3833                                 CC_MD5_Init(&md5State);
 
3834                                 ::lseek(fFileDescriptor, 0, SEEK_SET);
 
3836                                 while ( (len = ::read(fFileDescriptor, md5Buffer, kMD5BufferSize)) > 0 ) 
 
3837                                         CC_MD5_Update(&md5State, md5Buffer, len);
 
3838                                 CC_MD5_Final(digest, &md5State);
 
3842                                 // if malloc fails, fall back to random uuid
 
3843                                 ::uuid_generate_random(digest);
 
3845                         fUUIDAtom->setContent(digest);
 
3846                         uint32_t uuidOffset = ((SectionInfo*)fUUIDAtom->getSection())->fFileOffset + fUUIDAtom->getSectionOffset();
 
3847                         fUUIDAtom->copyRawContent(atomBuffer);
 
3848                         ::pwrite(fFileDescriptor, atomBuffer, fUUIDAtom->getSize(), uuidOffset);
 
3851                         // if output file fit in memory, just genrate an md5 hash in memory
 
3852                         CC_MD5(wholeBuffer, size, digest);
 
3853                         fUUIDAtom->setContent(digest);
 
3854                         uint32_t uuidOffset = ((SectionInfo*)fUUIDAtom->getSection())->fFileOffset + fUUIDAtom->getSectionOffset();
 
3855                         fUUIDAtom->copyRawContent(&wholeBuffer[uuidOffset]);
 
3861                 delete [] atomBuffer;
 
3864                 // write whole output file in one chunk
 
3865                 ::pwrite(fFileDescriptor, wholeBuffer, size, 0);
 
3866                 delete [] wholeBuffer;
 
3869         close(fFileDescriptor);
 
3875 void Writer<x86>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
3877         uint32_t* fixUp = (uint32_t*)&buffer[ref->getFixUpOffset()];
 
3878         uint8_t*  dtraceProbeSite;
 
3879         const int64_t kTwoGigLimit = 0x7FFFFFFF;
 
3880         const int64_t kSixtyFourKiloLimit = 0x7FFF;
 
3881         int64_t displacement;
 
3882         x86::ReferenceKinds kind = (x86::ReferenceKinds)(ref->getKind());
 
3885                 case x86::kFollowOn:
 
3888                 case x86::kPointerWeakImport:
 
3891                                 if ( this->relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal ) {
 
3892                                         if ( fOptions.prebind() ) {
 
3893                                                 switch (ref->getTarget().getDefinitionKind()) {
 
3894                                                         case ObjectFile::Atom::kExternalDefinition:
 
3895                                                         case ObjectFile::Atom::kExternalWeakDefinition:
 
3896                                                                 // prebound external relocation ==> pointer contains addend
 
3897                                                                 LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
3899                                                         case ObjectFile::Atom::kTentativeDefinition:
 
3900                                                         case ObjectFile::Atom::kRegularDefinition:
 
3901                                                         case ObjectFile::Atom::kWeakDefinition:
 
3902                                                                 // prebound external relocation to internal atom ==> pointer contains target address + addend
 
3903                                                                 LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
3905                                                         case ObjectFile::Atom::kAbsoluteSymbol:
 
3910                                                 // external realocation ==> pointer contains addend
 
3911                                                 LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
3915                                         // pointer contains target address
 
3916                                         //printf("Atom::fixUpReferenceFinal() target.name=%s, target.address=0x%08llX\n", target.getDisplayName(), target.getAddress());
 
3917                                         LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
3921                 case x86::kPointerDiff:
 
3922                         displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
3923                         LittleEndian::set32(*fixUp, (uint32_t)displacement);
 
3925                 case x86::kPointerDiff16:
 
3926                         displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
3927                         if ( (displacement > kSixtyFourKiloLimit) || (displacement < -(kSixtyFourKiloLimit)) ) 
 
3928                                 throwf("16-bit pointer diff out of range in %s", inAtom->getDisplayName());
 
3929                         LittleEndian::set16(*((uint16_t*)fixUp), (uint16_t)displacement);
 
3931                 case x86::kDtraceProbeSite:
 
3932                         // change call site to a NOP
 
3933                         dtraceProbeSite = (uint8_t*)fixUp;
 
3934                         dtraceProbeSite[-1] = 0x90;     // 1-byte nop
 
3935                         dtraceProbeSite[0] = 0x0F;      // 4-byte nop 
 
3936                         dtraceProbeSite[1] = 0x1F;
 
3937                         dtraceProbeSite[2] = 0x40;
 
3938                         dtraceProbeSite[3] = 0x00;
 
3940                 case x86::kDtraceIsEnabledSite:
 
3941                         // change call site to a clear eax
 
3942                         dtraceProbeSite = (uint8_t*)fixUp;
 
3943                         dtraceProbeSite[-1] = 0x33;             // xorl eax,eax
 
3944                         dtraceProbeSite[0] = 0xC0;
 
3945                         dtraceProbeSite[1] = 0x90;              // 1-byte nop
 
3946                         dtraceProbeSite[2] = 0x90;              // 1-byte nop
 
3947                         dtraceProbeSite[3] = 0x90;              // 1-byte nop
 
3949                 case x86::kPCRel32WeakImport:
 
3953                         switch ( ref->getTarget().getDefinitionKind() ) {
 
3954                                 case ObjectFile::Atom::kRegularDefinition:
 
3955                                 case ObjectFile::Atom::kWeakDefinition:
 
3956                                         displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
3958                                 case ObjectFile::Atom::kExternalDefinition:
 
3959                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
3960                                         throw "codegen problem, can't use rel32 to external symbol";
 
3961                                 case ObjectFile::Atom::kTentativeDefinition:
 
3964                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
3965                                         displacement = (ref->getTarget().getSectionOffset() + ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
3968                         if ( kind == x86::kPCRel16 ) {
 
3969                                 if ( (displacement > kSixtyFourKiloLimit) || (displacement < -(kSixtyFourKiloLimit)) ) {
 
3970                                         //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());
 
3971                                         throwf("rel16 out of range in %s", inAtom->getDisplayName());
 
3973                                 LittleEndian::set16(*((uint16_t*)fixUp), (uint16_t)displacement);
 
3976                                 if ( (displacement > kTwoGigLimit) || (displacement < (-kTwoGigLimit)) ) {
 
3977                                         //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());
 
3978                                         throwf("rel32 out of range in %s", inAtom->getDisplayName());
 
3980                                 LittleEndian::set32(*fixUp, (int32_t)displacement);
 
3983                 case x86::kAbsolute32:
 
3984                         switch ( ref->getTarget().getDefinitionKind() ) {
 
3985                                 case ObjectFile::Atom::kRegularDefinition:
 
3986                                 case ObjectFile::Atom::kWeakDefinition:
 
3987                                 case ObjectFile::Atom::kTentativeDefinition:
 
3988                                         // pointer contains target address
 
3989                                         LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
3991                                 case ObjectFile::Atom::kExternalDefinition:
 
3992                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
3993                                         // external realocation ==> pointer contains addend
 
3994                                         LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
3996                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
3997                                         // pointer contains target address
 
3998                                         LittleEndian::set32(*fixUp, ref->getTarget().getSectionOffset() + ref->getTargetOffset());
 
4002                 case x86::kDtraceTypeReference:
 
4003                 case x86::kDtraceProbe:
 
4004                         // nothing to fix up
 
4012 void Writer<x86>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
4014         const int64_t kTwoGigLimit = 0x7FFFFFFF;
 
4015         const int64_t kSixtyFourKiloLimit = 0x7FFF;
 
4016         uint32_t* fixUp = (uint32_t*)&buffer[ref->getFixUpOffset()];
 
4017         bool isExtern = this->makesExternalRelocatableReference(ref->getTarget());      
 
4018         int64_t displacement;
 
4019         x86::ReferenceKinds kind = (x86::ReferenceKinds)(ref->getKind());
 
4022                 case x86::kFollowOn:
 
4026                 case x86::kPointerWeakImport:
 
4027                 case x86::kAbsolute32:
 
4030                                         // external realocation ==> pointer contains addend
 
4031                                         LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
4033                                 else if ( ((SectionInfo*)inAtom->getSection())->fAllNonLazyPointers ) {
 
4034                                         // if INDIRECT_SYMBOL_LOCAL the content is pointer, else it is zero
 
4035                                         if ( this->indirectSymbolIsLocal(ref) ) 
 
4036                                                 LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
4038                                                 LittleEndian::set32(*fixUp, 0);
 
4040                                 else if ( ref->getTarget().getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition ) {
 
4041                                         // internal relocation => pointer contains target address
 
4042                                         LittleEndian::set32(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
4045                                         // internal relocation to tentative ==> pointer contains addend
 
4046                                         LittleEndian::set32(*fixUp, ref->getTargetOffset());
 
4050                 case x86::kPointerDiff:
 
4051                                 displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
4052                                 LittleEndian::set32(*fixUp, (uint32_t)displacement);
 
4054                 case x86::kPointerDiff16:
 
4055                                 displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
4056                                 if ( (displacement > kSixtyFourKiloLimit) || (displacement < -(kSixtyFourKiloLimit)) ) 
 
4057                                         throwf("16-bit pointer diff out of range in %s", inAtom->getDisplayName());
 
4058                                 LittleEndian::set16(*((uint16_t*)fixUp), (uint16_t)displacement);
 
4062                 case x86::kPCRel32WeakImport:
 
4063                 case x86::kDtraceProbeSite:
 
4064                 case x86::kDtraceIsEnabledSite:
 
4067                                         displacement = ref->getTargetOffset() - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
4069                                         displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
4070                                 if ( kind == x86::kPCRel16 ) {
 
4072                                         if ( (displacement > kSixtyFourKiloLimit) || (displacement < -(kSixtyFourKiloLimit)) ) {
 
4073                                                 //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());
 
4074                                                 throwf("rel16 out of range in %s", inAtom->getDisplayName());
 
4076                                         int16_t word = (int16_t)displacement;
 
4077                                         LittleEndian::set16(*((uint16_t*)fixUp), word);
 
4080                                         if ( (displacement > kTwoGigLimit) || (displacement < (-kTwoGigLimit)) ) {
 
4081                                                 //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());
 
4082                                                 throwf("rel32 out of range in %s", inAtom->getDisplayName());
 
4084                                         LittleEndian::set32(*fixUp, (int32_t)displacement);
 
4088                 case x86::kDtraceProbe:
 
4089                 case x86::kDtraceTypeReference:
 
4090                         // nothing to fix up
 
4096 void Writer<x86_64>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
4098         const int64_t twoGigLimit                 = 0x7FFFFFFF;
 
4099         uint64_t* fixUp = (uint64_t*)&buffer[ref->getFixUpOffset()];
 
4100         uint8_t*  dtraceProbeSite;
 
4101         int64_t displacement = 0;
 
4102         switch ( (x86_64::ReferenceKinds)(ref->getKind()) ) {
 
4103                 case x86_64::kNoFixUp:
 
4104                 case x86_64::kFollowOn:
 
4107                 case x86_64::kPointerWeakImport:
 
4108                 case x86_64::kPointer:
 
4110                                 //fprintf(stderr, "fixUpReferenceFinal: %s reference to %s\n", this->getDisplayName(), target.getDisplayName());
 
4111                                 if ( this->relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal ) {
 
4112                                         // external realocation ==> pointer contains addend
 
4113                                         LittleEndian::set64(*fixUp, ref->getTargetOffset());
 
4116                                         // internal relocation
 
4117                                         // pointer contains target address
 
4118                                         //printf("Atom::fixUpReferenceFinal) target.name=%s, target.address=0x%08llX\n", target.getDisplayName(), target.getAddress());
 
4119                                         LittleEndian::set64(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
4123                 case x86_64::kPointerDiff32:
 
4124                                 displacement = (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset());
 
4125                                 if ( (displacement > twoGigLimit) || (displacement < (-twoGigLimit)) )
 
4126                                         throw "32-bit pointer difference out of range";
 
4127                                 LittleEndian::set32(*((uint32_t*)fixUp), (uint32_t)displacement);
 
4129                 case x86_64::kPointerDiff:
 
4130                                 LittleEndian::set64(*fixUp,
 
4131                                         (ref->getTarget().getAddress() + ref->getTargetOffset()) - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
 
4133                 case x86_64::kPCRel32GOTLoad:
 
4134                 case x86_64::kPCRel32GOTLoadWeakImport:
 
4135                         // if GOT entry was optimized away, change movq instruction to a leaq
 
4136                         if ( std::find(fAllSynthesizedNonLazyPointers.begin(), fAllSynthesizedNonLazyPointers.end(), &(ref->getTarget())) == fAllSynthesizedNonLazyPointers.end() ) {
 
4137                                 //fprintf(stderr, "GOT for %s optimized away\n", ref->getTarget().getDisplayName());
 
4138                                 uint8_t* opcodes = (uint8_t*)fixUp;
 
4139                                 if ( opcodes[-2] != 0x8B )
 
4140                                         throw "GOT load reloc does not point to a movq instruction";
 
4143                         // fall into general rel32 case
 
4144                 case x86_64::kBranchPCRel32WeakImport:
 
4145                 case x86_64::kBranchPCRel32:
 
4146                 case x86_64::kPCRel32:
 
4147                 case x86_64::kPCRel32_1:
 
4148                 case x86_64::kPCRel32_2:
 
4149                 case x86_64::kPCRel32_4:
 
4150                 case x86_64::kPCRel32GOT:
 
4151                 case x86_64::kPCRel32GOTWeakImport:
 
4152                         switch ( ref->getTarget().getDefinitionKind() ) {
 
4153                                 case ObjectFile::Atom::kRegularDefinition:
 
4154                                 case ObjectFile::Atom::kWeakDefinition:
 
4155                                 case ObjectFile::Atom::kTentativeDefinition:
 
4156                                         displacement = (ref->getTarget().getAddress() + (int32_t)ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
4158                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
4159                                         displacement = (ref->getTarget().getSectionOffset() + (int32_t)ref->getTargetOffset()) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
4161                                 case ObjectFile::Atom::kExternalDefinition:
 
4162                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
4163                                         throw "codegen problem, can't use rel32 to external symbol";
 
4166                         switch ( ref->getKind() ) {
 
4167                                 case x86_64::kPCRel32_1:
 
4170                                 case x86_64::kPCRel32_2:
 
4173                                 case x86_64::kPCRel32_4:
 
4177                         if ( (displacement > twoGigLimit) || (displacement < (-twoGigLimit)) ) {
 
4178                                 fprintf(stderr, "call out of range from %s (%llX) in %s to %s (%llX) in %s\n", 
 
4179                                         inAtom->getDisplayName(), inAtom->getAddress(), inAtom->getFile()->getPath(), ref->getTarget().getDisplayName(), ref->getTarget().getAddress(), ref->getTarget().getFile()->getPath());
 
4180                                 throw "rel32 out of range";
 
4182                         LittleEndian::set32(*((uint32_t*)fixUp), (int32_t)displacement);
 
4184                 case x86_64::kDtraceProbeSite:
 
4185                         // change call site to a NOP
 
4186                         dtraceProbeSite = (uint8_t*)fixUp;
 
4187                         dtraceProbeSite[-1] = 0x90;     // 1-byte nop
 
4188                         dtraceProbeSite[0] = 0x0F;      // 4-byte nop 
 
4189                         dtraceProbeSite[1] = 0x1F;
 
4190                         dtraceProbeSite[2] = 0x40;
 
4191                         dtraceProbeSite[3] = 0x00;
 
4193                 case x86_64::kDtraceIsEnabledSite:
 
4194                         // change call site to a clear eax
 
4195                         dtraceProbeSite = (uint8_t*)fixUp;
 
4196                         dtraceProbeSite[-1] = 0x48;             // xorq eax,eax
 
4197                         dtraceProbeSite[0] = 0x33;
 
4198                         dtraceProbeSite[1] = 0xC0;              
 
4199                         dtraceProbeSite[2] = 0x90;              // 1-byte nop
 
4200                         dtraceProbeSite[3] = 0x90;              // 1-byte nop
 
4202                 case x86_64::kDtraceTypeReference:
 
4203                 case x86_64::kDtraceProbe:
 
4204                         // nothing to fix up
 
4210 void Writer<x86_64>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
4212         const int64_t twoGigLimit                 = 0x7FFFFFFF;
 
4213         bool external = this->makesExternalRelocatableReference(ref->getTarget());
 
4214         uint64_t* fixUp = (uint64_t*)&buffer[ref->getFixUpOffset()];
 
4215         int64_t displacement = 0;
 
4217         switch ( (x86_64::ReferenceKinds)(ref->getKind()) ) {
 
4218                 case x86_64::kNoFixUp:
 
4219                 case x86_64::kFollowOn:
 
4222                 case x86_64::kPointer:
 
4223                 case x86_64::kPointerWeakImport:
 
4226                                         // external realocation ==> pointer contains addend
 
4227                                         LittleEndian::set64(*fixUp, ref->getTargetOffset());
 
4230                                         // internal relocation ==> pointer contains target address
 
4231                                         LittleEndian::set64(*fixUp, ref->getTarget().getAddress() + ref->getTargetOffset());
 
4235                 case x86_64::kPointerDiff32:
 
4236                                 // addend in content
 
4237                                 LittleEndian::set32(*((uint32_t*)fixUp), ref->getTargetOffset() - ref->getFromTargetOffset() );
 
4239                 case x86_64::kPointerDiff:
 
4240                                 // addend in content
 
4241                                 LittleEndian::set64(*fixUp, ref->getTargetOffset() - ref->getFromTargetOffset() );
 
4243                 case x86_64::kBranchPCRel32:
 
4244                 case x86_64::kBranchPCRel32WeakImport:
 
4245                 case x86_64::kDtraceProbeSite:
 
4246                 case x86_64::kDtraceIsEnabledSite:
 
4247                 case x86_64::kPCRel32:
 
4248                 case x86_64::kPCRel32_1:
 
4249                 case x86_64::kPCRel32_2:
 
4250                 case x86_64::kPCRel32_4:
 
4251                         // turn unsigned 64-bit target offset in signed 32-bit offset, since that is what source originally had
 
4252                         temp32 = ref->getTargetOffset();
 
4254                                 // extern relocation contains addend
 
4255                                 displacement = temp32;
 
4258                                 // internal relocations contain delta to target address
 
4259                                 displacement = (ref->getTarget().getAddress() + temp32) - (inAtom->getAddress() + ref->getFixUpOffset() + 4);
 
4261                         switch ( ref->getKind() ) {
 
4262                                 case x86_64::kPCRel32_1:
 
4265                                 case x86_64::kPCRel32_2:
 
4268                                 case x86_64::kPCRel32_4:
 
4272                         if ( (displacement > twoGigLimit) || (displacement < (-twoGigLimit)) ) {
 
4273                                 //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());
 
4274                                 throw "rel32 out of range";
 
4276                         LittleEndian::set32(*((uint32_t*)fixUp), (int32_t)displacement);
 
4278                 case x86_64::kPCRel32GOT:
 
4279                 case x86_64::kPCRel32GOTLoad:
 
4280                 case x86_64::kPCRel32GOTWeakImport:
 
4281                 case x86_64::kPCRel32GOTLoadWeakImport:
 
4282                         // contains addend (usually zero)
 
4283                         LittleEndian::set32(*((uint32_t*)fixUp), (uint32_t)(ref->getTargetOffset()));
 
4285                 case x86_64::kDtraceTypeReference:
 
4286                 case x86_64::kDtraceProbe:
 
4287                         // nothing to fix up
 
4293 void Writer<ppc>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
4295         fixUpReference_powerpc(ref, inAtom, buffer, true);
 
4299 void Writer<ppc64>::fixUpReferenceFinal(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
4301         fixUpReference_powerpc(ref, inAtom, buffer, true);
 
4305 void Writer<ppc>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
4307         fixUpReference_powerpc(ref, inAtom, buffer, false);
 
4311 void Writer<ppc64>::fixUpReferenceRelocatable(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[]) const
 
4313         fixUpReference_powerpc(ref, inAtom, buffer, false);
 
4317 // ppc and ppc64 are mostly the same, so they share a template specialzation
 
4319 template <typename A>
 
4320 void Writer<A>::fixUpReference_powerpc(const ObjectFile::Reference* ref, const ObjectFile::Atom* inAtom, uint8_t buffer[], bool finalLinkedImage) const
 
4322         uint32_t        instruction;
 
4323         uint32_t        newInstruction;
 
4324         int64_t         displacement;
 
4325         uint64_t        targetAddr = 0;
 
4326         uint64_t        picBaseAddr;
 
4327         uint16_t        instructionLowHalf;
 
4328         uint16_t        instructionHighHalf;
 
4329         uint32_t*       fixUp = (uint32_t*)&buffer[ref->getFixUpOffset()];
 
4330         pint_t*         fixUpPointer = (pint_t*)&buffer[ref->getFixUpOffset()];
 
4331         bool            relocateableExternal = false;
 
4332         const int64_t picbase_twoGigLimit = 0x80000000;
 
4334         if ( ref->getTargetBinding() != ObjectFile::Reference::kDontBind ) {
 
4335                 targetAddr = ref->getTarget().getAddress() + ref->getTargetOffset();
 
4336                 if ( finalLinkedImage )
 
4337                         relocateableExternal = (relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal);
 
4339                         relocateableExternal = this->makesExternalRelocatableReference(ref->getTarget());       
 
4342         switch ( (typename A::ReferenceKinds)(ref->getKind()) ) {
 
4347                 case A::kPointerWeakImport:
 
4350                                 //fprintf(stderr, "fixUpReferenceFinal: %s reference to %s\n", this->getDisplayName(), target.getDisplayName());
 
4351                                 if ( finalLinkedImage && ((SectionInfo*)inAtom->getSection())->fAllLazyPointers ) {
 
4352                                         if ( fOptions.prebind() ) {
 
4353                                                 switch (ref->getTarget().getDefinitionKind()) {
 
4354                                                         case ObjectFile::Atom::kExternalDefinition:
 
4355                                                         case ObjectFile::Atom::kExternalWeakDefinition:
 
4356                                                                 // prebound lazy pointer to another dylib ==> pointer contains zero
 
4357                                                                 P::setP(*fixUpPointer, 0);
 
4359                                                         case ObjectFile::Atom::kTentativeDefinition:
 
4360                                                         case ObjectFile::Atom::kRegularDefinition:
 
4361                                                         case ObjectFile::Atom::kWeakDefinition:
 
4362                                                                 // prebound lazy pointer to withing this dylib ==> pointer contains address
 
4363                                                                 P::setP(*fixUpPointer, targetAddr);
 
4365                                                         case ObjectFile::Atom::kAbsoluteSymbol:
 
4370                                                 // lazy-symbol ==> pointer contains address of dyld_stub_binding_helper (stored in "from" target)
 
4371                                                 if ( fDyldHelper == NULL )
 
4372                                                         throw "symbol dyld_stub_binding_helper not defined (usually in crt1.o/dylib1.o/bundle1.o)";
 
4373                                                 P::setP(*fixUpPointer, fDyldHelper->getAddress());
 
4376                                 else if ( !finalLinkedImage && ((SectionInfo*)inAtom->getSection())->fAllNonLazyPointers ) {
 
4377                                         // if INDIRECT_SYMBOL_LOCAL the content is pointer, else it is zero
 
4378                                         if ( this->indirectSymbolIsLocal(ref) ) 
 
4379                                                 P::setP(*fixUpPointer, targetAddr);
 
4381                                                 P::setP(*fixUpPointer, 0);
 
4383                                 else if ( relocateableExternal ) {
 
4384                                         if ( fOptions.prebind() ) {
 
4385                                                 switch (ref->getTarget().getDefinitionKind()) {
 
4386                                                         case ObjectFile::Atom::kExternalDefinition:
 
4387                                                         case ObjectFile::Atom::kExternalWeakDefinition:
 
4388                                                                 // prebound external relocation ==> pointer contains addend
 
4389                                                                 P::setP(*fixUpPointer, ref->getTargetOffset());
 
4391                                                         case ObjectFile::Atom::kTentativeDefinition:
 
4392                                                         case ObjectFile::Atom::kRegularDefinition:
 
4393                                                         case ObjectFile::Atom::kWeakDefinition:
 
4394                                                                 // prebound external relocation to internal atom ==> pointer contains target address + addend
 
4395                                                                 P::setP(*fixUpPointer, targetAddr);
 
4397                                                         case ObjectFile::Atom::kAbsoluteSymbol:
 
4402                                                 // external realocation ==> pointer contains addend
 
4403                                                 P::setP(*fixUpPointer, ref->getTargetOffset());
 
4407                                         // internal relocation
 
4408                                         if ( finalLinkedImage || (ref->getTarget().getDefinitionKind() != ObjectFile::Atom::kTentativeDefinition)  ) {
 
4409                                                 // pointer contains target address
 
4410                                                 //printf("Atom::fixUpReference_powerpc() target.name=%s, target.address=0x%08llX\n",  ref->getTarget().getDisplayName(), targetAddr);
 
4411                                                 P::setP(*fixUpPointer, targetAddr);
 
4414                                                 // pointer contains addend
 
4415                                                 P::setP(*fixUpPointer, ref->getTargetOffset());
 
4420                 case A::kPointerDiff64:
 
4421                         P::setP(*fixUpPointer, targetAddr - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
 
4423                 case A::kPointerDiff32:
 
4424                         P::E::set32(*fixUp, targetAddr - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
 
4426                 case A::kPointerDiff16:
 
4427                         P::E::set16(*((uint16_t*)fixUp), targetAddr - (ref->getFromTarget().getAddress() + ref->getFromTargetOffset()) );
 
4429                 case A::kDtraceProbeSite:
 
4430                         if ( finalLinkedImage ) {
 
4431                                 // change call site to a NOP
 
4432                                 BigEndian::set32(*fixUp, 0x60000000);
 
4435                                 // set  bl instuction to branch to address zero in .o file
 
4436                                 int64_t displacement = ref->getTargetOffset() - (inAtom->getAddress() + ref->getFixUpOffset());
 
4437                                 instruction = BigEndian::get32(*fixUp);
 
4438                                 newInstruction = (instruction & 0xFC000003) | ((uint32_t)displacement & 0x03FFFFFC);
 
4439                                 BigEndian::set32(*fixUp, newInstruction);
 
4442                 case A::kDtraceIsEnabledSite:
 
4443                         if ( finalLinkedImage ) {
 
4444                                 // change call site to a li r3,0
 
4445                                 BigEndian::set32(*fixUp, 0x38600000);
 
4448                                 // set  bl instuction to branch to address zero in .o file
 
4449                                 int64_t displacement = ref->getTargetOffset() - (inAtom->getAddress() + ref->getFixUpOffset());
 
4450                                 instruction = BigEndian::get32(*fixUp);
 
4451                                 newInstruction = (instruction & 0xFC000003) | ((uint32_t)displacement & 0x03FFFFFC);
 
4452                                 BigEndian::set32(*fixUp, newInstruction);
 
4455                 case A::kBranch24WeakImport:
 
4458                                 //fprintf(stderr, "bl fixup to %s at 0x%08llX, ", target.getDisplayName(), target.getAddress());
 
4459                                 int64_t displacement = targetAddr - (inAtom->getAddress() + ref->getFixUpOffset());
 
4460                                 if ( relocateableExternal )  {
 
4461                                         // doing "ld -r" to an external symbol
 
4462                                         // the mach-o way of encoding this is that the bl instruction's target addr is the offset into the target
 
4463                                         displacement -= ref->getTarget().getAddress();
 
4466                                         const int64_t bl_eightMegLimit = 0x00FFFFFF;
 
4467                                         if ( (displacement > bl_eightMegLimit) || (displacement < (-bl_eightMegLimit)) ) {
 
4468                                                 //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());
 
4469                                                 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",
 
4470                                                         displacement, inAtom->getDisplayName(), inAtom->getAddress(), inAtom->getSectionName(), inAtom->getFile()->getPath(),
 
4471                                                         ref->getTarget().getDisplayName(), ref->getTarget().getAddress(), ref->getTarget().getSectionName(), ref->getTarget().getFile()->getPath());
 
4474                                 instruction = BigEndian::get32(*fixUp);
 
4475                                 newInstruction = (instruction & 0xFC000003) | ((uint32_t)displacement & 0x03FFFFFC);
 
4476                                 //fprintf(stderr, "bl fixup: 0x%08X -> 0x%08X\n", instruction, newInstruction);
 
4477                                 BigEndian::set32(*fixUp, newInstruction);
 
4482                                 //fprintf(stderr, "bc fixup %p to %s+0x%08X == 0x%08llX\n", this, ref->getTarget().getDisplayName(), ref->getTargetOffset(), targetAddr);
 
4483                                 int64_t displacement = targetAddr - (inAtom->getAddress() + ref->getFixUpOffset());
 
4484                                 if ( relocateableExternal )  {
 
4485                                         // doing "ld -r" to an external symbol
 
4486                                         // the mach-o way of encoding this is that the bl instruction's target addr is the offset into the target
 
4487                                         displacement -= ref->getTarget().getAddress();
 
4490                                         const int64_t b_sixtyFourKiloLimit = 0x0000FFFF;
 
4491                                         if ( (displacement > b_sixtyFourKiloLimit) || (displacement < (-b_sixtyFourKiloLimit)) ) {
 
4492                                                 //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());
 
4493                                                 throwf("bc out of range (%lld max is +/-64K) from %s in %s to %s in %s",
 
4494                                                         displacement, inAtom->getDisplayName(), inAtom->getFile()->getPath(),
 
4495                                                         ref->getTarget().getDisplayName(), ref->getTarget().getFile()->getPath());
 
4498                                 //fprintf(stderr, "bc fixup displacement=0x%08llX, atom.addr=0x%08llX, atom.offset=0x%08X\n", displacement, inAtom->getAddress(), (uint32_t)ref->getFixUpOffset());
 
4499                                 instruction = BigEndian::get32(*fixUp);
 
4500                                 newInstruction = (instruction & 0xFFFF0003) | ((uint32_t)displacement & 0x0000FFFC);
 
4501                                 //fprintf(stderr, "bc fixup: 0x%08X -> 0x%08X\n", instruction, newInstruction);
 
4502                                 BigEndian::set32(*fixUp, newInstruction);
 
4505                 case A::kPICBaseLow16:
 
4506                         picBaseAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
 
4507                         displacement = targetAddr - picBaseAddr;
 
4508                         if ( (displacement > picbase_twoGigLimit) || (displacement < (-picbase_twoGigLimit)) )
 
4509                                 throw "32-bit pic-base out of range";
 
4510                         instructionLowHalf = (displacement & 0xFFFF);
 
4511                         instruction = BigEndian::get32(*fixUp);
 
4512                         newInstruction = (instruction & 0xFFFF0000) | instructionLowHalf;
 
4513                         BigEndian::set32(*fixUp, newInstruction);
 
4515                 case A::kPICBaseLow14:
 
4516                         picBaseAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
 
4517                         displacement = targetAddr - picBaseAddr;
 
4518                         if ( (displacement > picbase_twoGigLimit) || (displacement < (-picbase_twoGigLimit)) )
 
4519                                 throw "32-bit pic-base out of range";
 
4520                         if ( (displacement & 0x3) != 0 )
 
4521                                 throwf("bad offset (0x%08X) for lo14 instruction pic-base fix-up", (uint32_t)displacement);
 
4522                         instructionLowHalf = (displacement & 0xFFFC);
 
4523                         instruction = BigEndian::get32(*fixUp);
 
4524                         newInstruction = (instruction & 0xFFFF0003) | instructionLowHalf;
 
4525                         BigEndian::set32(*fixUp, newInstruction);
 
4527                 case A::kPICBaseHigh16:
 
4528                         picBaseAddr = ref->getFromTarget().getAddress() + ref->getFromTargetOffset();
 
4529                         displacement = targetAddr - picBaseAddr;
 
4530                         if ( (displacement > picbase_twoGigLimit) || (displacement < (-picbase_twoGigLimit)) )
 
4531                                 throw "32-bit pic-base out of range";
 
4532                         instructionLowHalf = displacement >> 16;
 
4533                         if ( (displacement & 0x00008000) != 0 )
 
4534                                 ++instructionLowHalf;
 
4535                         instruction = BigEndian::get32(*fixUp);
 
4536                         newInstruction = (instruction & 0xFFFF0000) | instructionLowHalf;
 
4537                         BigEndian::set32(*fixUp, newInstruction);
 
4540                         if ( relocateableExternal && !finalLinkedImage )
 
4541                                 targetAddr -= ref->getTarget().getAddress();
 
4542                         instructionLowHalf = (targetAddr & 0xFFFF);
 
4543                         instruction = BigEndian::get32(*fixUp);
 
4544                         newInstruction = (instruction & 0xFFFF0000) | instructionLowHalf;
 
4545                         BigEndian::set32(*fixUp, newInstruction);
 
4548                         if ( relocateableExternal && !finalLinkedImage )
 
4549                                 targetAddr -= ref->getTarget().getAddress();
 
4550                         if ( (targetAddr & 0x3) != 0 )
 
4551                                 throw "bad address for absolute lo14 instruction fix-up";
 
4552                         instructionLowHalf = (targetAddr & 0xFFFF);
 
4553                         instruction = BigEndian::get32(*fixUp);
 
4554                         newInstruction = (instruction & 0xFFFF0003) | instructionLowHalf;
 
4555                         BigEndian::set32(*fixUp, newInstruction);
 
4558                         if ( relocateableExternal ) {
 
4559                                 if ( finalLinkedImage ) {
 
4560                                         switch (ref->getTarget().getDefinitionKind()) {
 
4561                                                 case ObjectFile::Atom::kExternalDefinition:
 
4562                                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
4563                                                         throwf("absolute address to symbol %s in a different linkage unit not supported", ref->getTargetName());
 
4565                                                 case ObjectFile::Atom::kTentativeDefinition:
 
4566                                                 case ObjectFile::Atom::kRegularDefinition:
 
4567                                                 case ObjectFile::Atom::kWeakDefinition:
 
4568                                                         // use target address
 
4570                                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
4571                                                         targetAddr = ref->getTarget().getSectionOffset();
 
4576                                         targetAddr -= ref->getTarget().getAddress();
 
4579                         instructionHighHalf = (targetAddr >> 16);
 
4580                         instruction = BigEndian::get32(*fixUp);
 
4581                         newInstruction = (instruction & 0xFFFF0000) | instructionHighHalf;
 
4582                         BigEndian::set32(*fixUp, newInstruction);
 
4584                 case A::kAbsHigh16AddLow:
 
4585                         if ( relocateableExternal ) {
 
4586                                 if ( finalLinkedImage ) {
 
4587                                         switch (ref->getTarget().getDefinitionKind()) {
 
4588                                                 case ObjectFile::Atom::kExternalDefinition:
 
4589                                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
4590                                                         throwf("absolute address to symbol %s in a different linkage unit not supported", ref->getTargetName());
 
4592                                                 case ObjectFile::Atom::kTentativeDefinition:
 
4593                                                 case ObjectFile::Atom::kRegularDefinition:
 
4594                                                 case ObjectFile::Atom::kWeakDefinition:
 
4595                                                         // use target address
 
4597                                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
4598                                                         targetAddr = ref->getTarget().getSectionOffset();
 
4603                                         targetAddr -= ref->getTarget().getAddress();
 
4606                         if ( targetAddr & 0x00008000 )
 
4607                                 targetAddr += 0x00010000;
 
4608                         instruction = BigEndian::get32(*fixUp);
 
4609                         newInstruction = (instruction & 0xFFFF0000) | (targetAddr >> 16);
 
4610                         BigEndian::set32(*fixUp, newInstruction);
 
4612                 case A::kDtraceTypeReference:
 
4613                 case A::kDtraceProbe:
 
4614                         // nothing to fix up
 
4620 bool Writer<ppc>::stubableReference(const ObjectFile::Reference* ref)
 
4622         uint8_t kind = ref->getKind();
 
4623         switch ( (ppc::ReferenceKinds)kind ) {
 
4625                 case ppc::kFollowOn:
 
4627                 case ppc::kPointerWeakImport:
 
4628                 case ppc::kPointerDiff16:
 
4629                 case ppc::kPointerDiff32:
 
4630                 case ppc::kPointerDiff64:
 
4631                 case ppc::kDtraceProbe:
 
4632                 case ppc::kDtraceProbeSite:
 
4633                 case ppc::kDtraceIsEnabledSite:
 
4634                 case ppc::kDtraceTypeReference:
 
4635                         // these are never used to call external functions
 
4637                 case ppc::kBranch24: 
 
4638                 case ppc::kBranch24WeakImport: 
 
4639                 case ppc::kBranch14: 
 
4640                         // these are used to call external functions
 
4642                 case ppc::kPICBaseLow16:
 
4643                 case ppc::kPICBaseLow14:
 
4644                 case ppc::kPICBaseHigh16:
 
4645                 case ppc::kAbsLow16:
 
4646                 case ppc::kAbsLow14:
 
4647                 case ppc::kAbsHigh16:
 
4648                 case ppc::kAbsHigh16AddLow:
 
4649                         // these are only used to call external functions
 
4650                         // in -mlong-branch stubs
 
4651                         switch ( ref->getTarget().getDefinitionKind() ) {
 
4652                                 case ObjectFile::Atom::kExternalDefinition:
 
4653                                 case ObjectFile::Atom::kExternalWeakDefinition:
 
4655                                 case ObjectFile::Atom::kTentativeDefinition:
 
4656                                 case ObjectFile::Atom::kRegularDefinition:
 
4657                                 case ObjectFile::Atom::kWeakDefinition:
 
4658                                 case ObjectFile::Atom::kAbsoluteSymbol:
 
4668 bool Writer<ppc64>::stubableReference(const ObjectFile::Reference* ref)
 
4670         uint8_t kind = ref->getKind();
 
4671         switch ( (ppc64::ReferenceKinds)kind ) {
 
4673                 case ppc::kFollowOn:
 
4675                 case ppc::kPointerWeakImport:
 
4676                 case ppc::kPointerDiff16:
 
4677                 case ppc::kPointerDiff32:
 
4678                 case ppc::kPointerDiff64:
 
4679                 case ppc::kPICBaseLow16:
 
4680                 case ppc::kPICBaseLow14:
 
4681                 case ppc::kPICBaseHigh16:
 
4682                 case ppc::kAbsLow16:
 
4683                 case ppc::kAbsLow14:
 
4684                 case ppc::kAbsHigh16:
 
4685                 case ppc::kAbsHigh16AddLow:
 
4686                 case ppc::kDtraceProbe:
 
4687                 case ppc::kDtraceProbeSite:
 
4688                 case ppc::kDtraceIsEnabledSite:
 
4689                 case ppc::kDtraceTypeReference:
 
4690                         // these are never used to call external functions
 
4692                 case ppc::kBranch24: 
 
4693                 case ppc::kBranch24WeakImport: 
 
4694                 case ppc::kBranch14: 
 
4695                         // these are used to call external functions
 
4702 bool Writer<x86>::stubableReference(const ObjectFile::Reference* ref)
 
4704         uint8_t kind = ref->getKind();
 
4705         return (kind == x86::kPCRel32 || kind == x86::kPCRel32WeakImport);
 
4709 bool Writer<x86_64>::stubableReference(const ObjectFile::Reference* ref)
 
4711         uint8_t kind = ref->getKind();
 
4712         return (kind == x86_64::kBranchPCRel32 || kind == x86_64::kBranchPCRel32WeakImport);
 
4717 bool Writer<ppc>::weakImportReferenceKind(uint8_t kind)
 
4719         return (kind == ppc::kBranch24WeakImport || kind == ppc::kPointerWeakImport);
 
4723 bool Writer<ppc64>::weakImportReferenceKind(uint8_t kind)
 
4725         return (kind == ppc64::kBranch24WeakImport || kind == ppc64::kPointerWeakImport);
 
4729 bool Writer<x86>::weakImportReferenceKind(uint8_t kind)
 
4731         return (kind == x86::kPCRel32WeakImport || kind == x86::kPointerWeakImport);
 
4735 bool Writer<x86_64>::weakImportReferenceKind(uint8_t kind)
 
4738                 case x86_64::kPointerWeakImport:
 
4739                 case x86_64::kBranchPCRel32WeakImport:
 
4740                 case x86_64::kPCRel32GOTWeakImport:
 
4741                 case x86_64::kPCRel32GOTLoadWeakImport:
 
4750 bool Writer<ppc>::GOTReferenceKind(uint8_t kind)
 
4756 bool Writer<ppc64>::GOTReferenceKind(uint8_t kind)
 
4762 bool Writer<x86>::GOTReferenceKind(uint8_t kind)
 
4768 bool Writer<x86_64>::GOTReferenceKind(uint8_t kind)
 
4771                 case x86_64::kPCRel32GOT:
 
4772                 case x86_64::kPCRel32GOTWeakImport:
 
4773                 case x86_64::kPCRel32GOTLoad:
 
4774                 case x86_64::kPCRel32GOTLoadWeakImport:
 
4781 bool Writer<ppc>::optimizableGOTReferenceKind(uint8_t kind)
 
4787 bool Writer<ppc64>::optimizableGOTReferenceKind(uint8_t kind)
 
4793 bool Writer<x86>::optimizableGOTReferenceKind(uint8_t kind)
 
4799 bool Writer<x86_64>::optimizableGOTReferenceKind(uint8_t kind)
 
4802                 case x86_64::kPCRel32GOTLoad:
 
4803                 case x86_64::kPCRel32GOTLoadWeakImport:
 
4811 // 64-bit architectures never need module table, 32-bit sometimes do for backwards compatiblity
 
4812 template <typename A> bool Writer<A>::needsModuleTable() {return fOptions.needsModuleTable(); }
 
4813 template <> bool Writer<ppc64>::needsModuleTable() { return false; }
 
4814 template <> bool Writer<x86_64>::needsModuleTable() { return false; }
 
4817 template <typename A>
 
4818 void Writer<A>::optimizeDylibReferences()
 
4820         //fprintf(stderr, "original ordinals table:\n");
 
4821         //for (std::map<class ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {
 
4822         //      fprintf(stderr, "%u <== %p/%s\n", it->second, it->first, it->first->getPath());
 
4824         // find unused dylibs that can be removed
 
4825         std::map<uint32_t, ObjectFile::Reader*> ordinalToReader;
 
4826         std::map<ObjectFile::Reader*, ObjectFile::Reader*> readerAliases;
 
4827         for (std::map<ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {   
 
4828                 ObjectFile::Reader* reader = it->first;
 
4829                 std::map<ObjectFile::Reader*, ObjectFile::Reader*>::iterator aliasPos = fLibraryAliases.find(reader);
 
4830                 if ( aliasPos != fLibraryAliases.end() ) {
 
4831                         // already noticed that this reader has same install name as another reader
 
4832                         readerAliases[reader] = aliasPos->second;
 
4834                 else if ( !reader->providedExportAtom() && (reader->implicitlyLinked() || fOptions.deadStripDylibs()) ) {
 
4835                         // this reader can be optimized away
 
4836                         it->second = 0xFFFFFFFF;
 
4837                         typename std::map<class ObjectFile::Reader*, class DylibLoadCommandsAtom<A>* >::iterator pos = fLibraryToLoadCommand.find(reader);
 
4838                         if ( pos != fLibraryToLoadCommand.end() ) 
 
4839                                 pos->second->optimizeAway();
 
4842                         // mark this reader as using it ordinal
 
4843                         std::map<uint32_t, ObjectFile::Reader*>::iterator pos = ordinalToReader.find(it->second);
 
4844                         if ( pos == ordinalToReader.end() ) 
 
4845                                 ordinalToReader[it->second] = reader;
 
4847                                 readerAliases[reader] = pos->second;
 
4850         // renumber ordinals (depends on iterator walking in ordinal order)
 
4851         uint32_t newOrdinal = 0;
 
4852         for (std::map<uint32_t, ObjectFile::Reader*>::iterator it = ordinalToReader.begin(); it != ordinalToReader.end(); ++it) {
 
4853                 if ( it->first <= fLibraryToOrdinal.size() )
 
4854                         fLibraryToOrdinal[it->second] = ++newOrdinal;
 
4857         // add aliases (e.g. -lm points to libSystem.dylib)
 
4858         for (std::map<ObjectFile::Reader*, ObjectFile::Reader*>::iterator it = readerAliases.begin(); it != readerAliases.end(); ++it) {
 
4859                 fLibraryToOrdinal[it->first] = fLibraryToOrdinal[it->second];
 
4862         // fprintf(stderr, "new ordinals table:\n");
 
4863         //for (std::map<class ObjectFile::Reader*, uint32_t>::iterator it = fLibraryToOrdinal.begin(); it != fLibraryToOrdinal.end(); ++it) {
 
4864         //      fprintf(stderr, "%u <== %p/%s\n", it->second, it->first, it->first->getPath());
 
4870 void Writer<x86_64>::scanForAbsoluteReferences()
 
4872         // x86_64 codegen never has absolute references
 
4876 void  Writer<x86>::scanForAbsoluteReferences()
 
4878         // when linking -pie verify there are no absolute addressing
 
4879         if ( fOptions.positionIndependentExecutable() ) {
 
4880                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
4881                         ObjectFile::Atom* atom = *it;
 
4882                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
4883                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
4884                                 ObjectFile::Reference* ref = *rit;
 
4885                                 switch (ref->getKind()) {
 
4886                                         case x86::kAbsolute32:
 
4887                                                 throwf("cannot link -pie: -mdynamic-no-pic codegen found in %s from %s\n", atom->getDisplayName(), atom->getFile()->getPath());
 
4896 void  Writer<ppc>::scanForAbsoluteReferences()
 
4898         // when linking -pie verify there are no absolute addressing
 
4899         if ( fOptions.positionIndependentExecutable() ) {
 
4900                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
4901                         ObjectFile::Atom* atom = *it;
 
4902                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
4903                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
4904                                 ObjectFile::Reference* ref = *rit;
 
4905                                 switch (ref->getKind()) {
 
4906                                         case ppc::kAbsLow16:
 
4907                                         case ppc::kAbsLow14:
 
4908                                         case ppc::kAbsHigh16:
 
4909                                         case ppc::kAbsHigh16AddLow:
 
4910                                                 throwf("cannot link -pie: -mdynamic-no-pic codegen found in %s from %s\n", atom->getDisplayName(), atom->getFile()->getPath());
 
4919 // for ppc64 look for any -mdynamic-no-pic codegen
 
4921 void  Writer<ppc64>::scanForAbsoluteReferences()
 
4923         // only do this for main executable
 
4924         if ( mightNeedPadSegment() && (fPageZeroAtom != NULL) ) {
 
4925                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
4926                         ObjectFile::Atom* atom = *it;
 
4927                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
4928                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
4929                                 ObjectFile::Reference* ref = *rit;
 
4930                                 switch (ref->getKind()) {
 
4931                                         case ppc64::kAbsLow16:
 
4932                                         case ppc64::kAbsLow14:
 
4933                                         case ppc64::kAbsHigh16:
 
4934                                         case ppc64::kAbsHigh16AddLow:
 
4935                                                 //fprintf(stderr, "found -mdynamic-no-pic codegen in %s in %s\n", atom->getDisplayName(), atom->getFile()->getPath());
 
4936                                                 // shrink page-zero and add pad segment to compensate
 
4937                                                 fPadSegmentInfo = new SegmentInfo();
 
4938                                                 strcpy(fPadSegmentInfo->fName, "__4GBFILL");
 
4939                                                 fPageZeroAtom->setSize(0x1000);
 
4948 template <typename A>
 
4949 void Writer<A>::insertDummyStubs()
 
4951         // only needed for x86
 
4955 void Writer<x86>::insertDummyStubs()
 
4957         // any 5-byte stubs that cross a 32-byte cache line may update incorrectly
 
4958         std::vector<class StubAtom<x86>*>        betterStubs;
 
4959         for (std::vector<class StubAtom<x86>*>::iterator it=fAllSynthesizedStubs.begin(); it != fAllSynthesizedStubs.end(); it++) {
 
4960                 switch (betterStubs.size() % 64 ) {
 
4961                         case 12:// stub would occupy 0x3C->0x41
 
4962                         case 25:// stub would occupy 0x7D->0x82
 
4963                         case 38:// stub would occupy 0xBE->0xC3
 
4964                         case 51:// stub would occupy 0xFF->0x04
 
4965                                 betterStubs.push_back(new StubAtom<x86>(*this, *((ObjectFile::Atom*)NULL))); //pad with dummy stub
 
4968                 betterStubs.push_back(*it);
 
4971         fAllSynthesizedStubs.clear();
 
4972         fAllSynthesizedStubs.insert(fAllSynthesizedStubs.begin(), betterStubs.begin(), betterStubs.end());
 
4975 template <typename A>
 
4976 void Writer<A>::synthesizeStubs()
 
4978         switch ( fOptions.outputKind() ) {
 
4979                 case Options::kObjectFile:
 
4980                         // these output kinds never have stubs
 
4982                 case Options::kStaticExecutable:
 
4983                 case Options::kDyld:
 
4984                 case Options::kDynamicLibrary:
 
4985                 case Options::kDynamicBundle:
 
4986                 case Options::kDynamicExecutable:
 
4987                         // try to synthesize stubs for these
 
4991         // walk every atom and reference
 
4992         for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
4993                 ObjectFile::Atom* atom = *it;
 
4994                 std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
4995                 for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
4996                         ObjectFile::Reference* ref = *rit;
 
4997                         switch ( ref->getTargetBinding()) {
 
4998                                 case ObjectFile::Reference::kUnboundByName:
 
4999                                 case ObjectFile::Reference::kDontBind:
 
5001                                 case ObjectFile::Reference::kBoundByName:
 
5002                                 case ObjectFile::Reference::kBoundDirectly:
 
5003                                         ObjectFile::Atom& target = ref->getTarget();
 
5004                                         // build map of which symbols need weak importing
 
5005                                         if ( (target.getDefinitionKind() == ObjectFile::Atom::kExternalDefinition)
 
5006                                                 || (target.getDefinitionKind() == ObjectFile::Atom::kExternalWeakDefinition) ) {
 
5007                                                 bool weakImport = this->weakImportReferenceKind(ref->getKind());
 
5008                                                 std::map<const ObjectFile::Atom*,bool>::iterator pos = fWeakImportMap.find(&target);
 
5009                                                 if ( pos == fWeakImportMap.end() ) {
 
5010                                                         // target not in fWeakImportMap, so add
 
5011                                                         fWeakImportMap[&target] = weakImport;
 
5014                                                         // target in fWeakImportMap, check for weakness mismatch
 
5015                                                         if ( pos->second != weakImport ) {
 
5017                                                                 switch ( fOptions.weakReferenceMismatchTreatment() ) {
 
5018                                                                         case Options::kWeakReferenceMismatchError:
 
5019                                                                                 throwf("mismatching weak references for symbol: %s", target.getName());
 
5020                                                                         case Options::kWeakReferenceMismatchWeak:
 
5023                                                                         case Options::kWeakReferenceMismatchNonWeak:
 
5024                                                                                 pos->second = false;
 
5030                                         // create stubs as needed
 
5031                                         if ( this->stubableReference(ref) 
 
5032                                                 && (ref->getTargetOffset() == 0)
 
5033                                                 && this->relocationNeededInFinalLinkedImage(target) == kRelocExternal ) {
 
5034                                                 ObjectFile::Atom* stub = NULL;
 
5035                                                 std::map<const ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fStubsMap.find(&target);
 
5036                                                 if ( pos == fStubsMap.end() ) {
 
5037                                                         stub = new StubAtom<A>(*this, target);
 
5038                                                         fStubsMap[&target] = stub;
 
5043                                                 // alter reference to use stub instead
 
5044                                                 ref->setTarget(*stub, 0);
 
5046                                         // create GOT slots (non-lazy pointers) as needed
 
5047                                         else if ( this->GOTReferenceKind(ref->getKind()) ) {
 
5049                                                 bool mustUseGOT = ( this->relocationNeededInFinalLinkedImage(ref->getTarget()) == kRelocExternal );
 
5051                                                 if ( fBiggerThanTwoGigs ) {
 
5052                                                         // in big images use GOT for all zero fill atoms
 
5053                                                         // this is just a heuristic and may need to be re-examined
 
5054                                                         useGOT = mustUseGOT || ref->getTarget().isZeroFill();
 
5057                                                         // < 2GB image so remove all GOT entries that we can
 
5058                                                         useGOT = mustUseGOT;
 
5060                                                 // if this GOT usage cannot be optimized away then make a GOT enry
 
5061                                                 if ( ! this->optimizableGOTReferenceKind(ref->getKind()) )
 
5064                                                         ObjectFile::Atom* nlp = NULL;
 
5065                                                         std::map<ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fGOTMap.find(&target);
 
5066                                                         if ( pos == fGOTMap.end() ) {
 
5067                                                                 nlp = new NonLazyPointerAtom<A>(*this, target);
 
5068                                                                 fGOTMap[&target] = nlp;
 
5073                                                         // alter reference to use non lazy pointer instead
 
5074                                                         ref->setTarget(*nlp, ref->getTargetOffset());
 
5082         std::sort(fAllSynthesizedStubs.begin(), fAllSynthesizedStubs.end(), AtomByNameSorter());
 
5084         // add dummy stubs (x86 only)
 
5085         this->insertDummyStubs();
 
5087         // sort lazy pointers
 
5088         std::sort(fAllSynthesizedLazyPointers.begin(), fAllSynthesizedLazyPointers.end(), AtomByNameSorter());
 
5090         // add stubs to fAllAtoms
 
5091         if ( fAllSynthesizedStubs.size() != 0 ) {
 
5092                 std::vector<ObjectFile::Atom*>* stubs = (std::vector<ObjectFile::Atom*>*)&fAllSynthesizedStubs;
 
5093                 std::vector<ObjectFile::Atom*> mergedStubs;
 
5094                 if ( fAllSynthesizedStubHelpers.size() != 0 ) {
 
5095                         // when we have stubs and helpers, insert both into fAllAtoms
 
5096                         mergedStubs.insert(mergedStubs.end(), fAllSynthesizedStubs.begin(), fAllSynthesizedStubs.end());
 
5097                         mergedStubs.insert(mergedStubs.end(), fAllSynthesizedStubHelpers.begin(), fAllSynthesizedStubHelpers.end());
 
5098                         stubs = &mergedStubs;
 
5100                 ObjectFile::Section* curSection = NULL;
 
5101                 ObjectFile::Atom* prevAtom = NULL;
 
5102                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
5103                         ObjectFile::Atom* atom = *it;
 
5104                         ObjectFile::Section* nextSection = atom->getSection();
 
5105                         if ( nextSection != curSection ) {
 
5106                                 // HACK HACK for i386 where stubs are not in _TEXT segment
 
5107                                 if ( strcmp(fAllSynthesizedStubs[0]->getSegment().getName(), "__IMPORT") == 0 ) {
 
5108                                         if ( ((prevAtom != NULL) && (strcmp(prevAtom->getSegment().getName(), "__IMPORT") == 0))
 
5109                                                 || (strcmp(atom->getSegment().getName(), "__LINKEDIT") == 0) ) {
 
5110                                                 // insert stubs at end of __IMPORT segment, or before __LINKEDIT
 
5111                                                 fAllAtoms->insert(it, fAllSynthesizedStubs.begin(), fAllSynthesizedStubs.end());
 
5116                                         if ( (prevAtom != NULL) && (strcmp(prevAtom->getSectionName(), "__text") == 0) ) {
 
5117                                                 // found end of __text section, insert stubs here
 
5118                                                 fAllAtoms->insert(it, stubs->begin(), stubs->end());
 
5122                                 curSection = nextSection;
 
5129         // add lazy pointers to fAllAtoms
 
5130         if ( fAllSynthesizedLazyPointers.size() != 0 ) {
 
5131                 ObjectFile::Section* curSection = NULL;
 
5132                 ObjectFile::Atom* prevAtom = NULL;
 
5133                 bool inserted = false;
 
5134                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
5135                         ObjectFile::Atom* atom = *it;
 
5136                         ObjectFile::Section* nextSection = atom->getSection();
 
5137                         if ( nextSection != curSection ) {
 
5138                                 if ( (prevAtom != NULL) && (strcmp(prevAtom->getSectionName(), "__dyld") == 0) ) {
 
5139                                         // found end of __dyld section, insert lazy pointers here
 
5140                                         fAllAtoms->insert(it, fAllSynthesizedLazyPointers.begin(), fAllSynthesizedLazyPointers.end());
 
5144                                 curSection = nextSection;
 
5149                         throw "can't insert lazy pointers, __dyld section not found";
 
5153         // add non-lazy pointers to fAllAtoms
 
5154         if ( fAllSynthesizedNonLazyPointers.size() != 0 ) {
 
5155                 ObjectFile::Section* curSection = NULL;
 
5156                 ObjectFile::Atom* prevAtom = NULL;
 
5157                 bool inserted = false;
 
5158                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
5159                         ObjectFile::Atom* atom = *it;
 
5160                         ObjectFile::Section* nextSection = atom->getSection();
 
5161                         if ( nextSection != curSection ) {
 
5162                                 if ( (prevAtom != NULL) 
 
5163                                         && ((strcmp(prevAtom->getSectionName(), "__dyld") == 0) 
 
5164                                         || ((strcmp(prevAtom->getSectionName(), "__data") == 0) &&
 
5165                                                 ((fOptions.outputKind() == Options::kDyld) || (fOptions.outputKind() == Options::kStaticExecutable))) ) ) {
 
5166                                         // found end of __dyld section, insert lazy pointers here
 
5167                                         fAllAtoms->insert(it, fAllSynthesizedNonLazyPointers.begin(), fAllSynthesizedNonLazyPointers.end());
 
5171                                 curSection = nextSection;
 
5176                         throw "can't insert non-lazy pointers, __dyld section not found";
 
5180         // build LC_SEGMENT_SPLIT_INFO content now that all atoms exist
 
5181         if ( fSplitCodeToDataContentAtom != NULL ) {
 
5182                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
5183                         ObjectFile::Atom* atom = *it;
 
5184                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
5185                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
5186                                 ObjectFile::Reference* ref = *rit;
 
5187                                 switch ( ref->getTargetBinding()) {
 
5188                                         case ObjectFile::Reference::kUnboundByName:
 
5189                                         case ObjectFile::Reference::kDontBind:
 
5191                                         case ObjectFile::Reference::kBoundByName:
 
5192                                         case ObjectFile::Reference::kBoundDirectly:
 
5193                                                 if ( this->segmentsCanSplitApart(*atom, ref->getTarget()) ) {
 
5194                                                         this->addCrossSegmentRef(atom, ref);
 
5205 template <typename A>
 
5206 void Writer<A>::partitionIntoSections()
 
5208         const bool oneSegmentCommand = (fOptions.outputKind() == Options::kObjectFile);
 
5210         // for every atom, set its sectionInfo object and section offset
 
5211         // build up fSegmentInfos along the way
 
5212         ObjectFile::Section* curSection = NULL;
 
5213         SectionInfo* currentSectionInfo = NULL;
 
5214         SegmentInfo* currentSegmentInfo = NULL;
 
5215         SectionInfo* cstringSectionInfo = NULL;
 
5216         unsigned int sectionIndex = 1;
 
5217         fSegmentInfos.reserve(8);
 
5218         for (unsigned int i=0; i < fAllAtoms->size(); ++i) {
 
5219                 ObjectFile::Atom* atom = (*fAllAtoms)[i];
 
5220                 if ( (atom->getSection() != curSection) || ((curSection==NULL) && (strcmp(atom->getSectionName(),currentSectionInfo->fSectionName) != 0)) ) {
 
5221                         if ( oneSegmentCommand ) {
 
5222                                 if ( currentSegmentInfo == NULL ) {
 
5223                                         currentSegmentInfo = new SegmentInfo();
 
5224                                         currentSegmentInfo->fInitProtection = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
 
5225                                         currentSegmentInfo->fMaxProtection = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
 
5226                                         this->fSegmentInfos.push_back(currentSegmentInfo);
 
5228                                 currentSectionInfo = new SectionInfo();
 
5229                                 strcpy(currentSectionInfo->fSectionName, atom->getSectionName());
 
5230                                 strcpy(currentSectionInfo->fSegmentName, atom->getSegment().getName());
 
5231                                 currentSectionInfo->fAlignment = atom->getAlignment().powerOf2;
 
5232                                 currentSectionInfo->fAllZeroFill = atom->isZeroFill();
 
5233                                 currentSectionInfo->fVirtualSection = (currentSectionInfo->fSectionName[0] == '.');
 
5234                                 if ( !currentSectionInfo->fVirtualSection || fEmitVirtualSections )
 
5235                                         currentSectionInfo->setIndex(sectionIndex++);
 
5236                                 currentSegmentInfo->fSections.push_back(currentSectionInfo);
 
5237                                 if ( (strcmp(currentSectionInfo->fSegmentName, "__TEXT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__cstring") == 0) ) 
 
5238                                         cstringSectionInfo = currentSectionInfo;
 
5241                                 if ( (currentSegmentInfo == NULL) || (strcmp(currentSegmentInfo->fName, atom->getSegment().getName()) != 0) ) {
 
5242                                         currentSegmentInfo = new SegmentInfo();
 
5243                                         strcpy(currentSegmentInfo->fName, atom->getSegment().getName());
 
5244                                         uint32_t initprot  = 0;
 
5245                                         if ( atom->getSegment().isContentReadable() )
 
5246                                                 initprot |= VM_PROT_READ;
 
5247                                         if ( atom->getSegment().isContentWritable() )
 
5248                                                 initprot |= VM_PROT_WRITE;
 
5249                                         if ( atom->getSegment().isContentExecutable() )
 
5250                                                 initprot |= VM_PROT_EXECUTE;
 
5251                                         if ( fOptions.readOnlyx86Stubs() && (strcmp(atom->getSegment().getName(), "__IMPORT") == 0) )
 
5252                                                 initprot &= ~VM_PROT_WRITE;     // hack until i386 __pointers section is synthesized by linker
 
5253                                         currentSegmentInfo->fInitProtection = initprot;
 
5254                                         if ( initprot == 0 )
 
5255                                                 currentSegmentInfo->fMaxProtection = 0;  // pagezero should have maxprot==initprot==0
 
5257                                                 currentSegmentInfo->fMaxProtection = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
 
5258                                         std::vector<Options::SegmentProtect>& customSegProtections = fOptions.customSegmentProtections();
 
5259                                         for(std::vector<Options::SegmentProtect>::iterator it = customSegProtections.begin(); it != customSegProtections.end(); ++it) {
 
5260                                                 if ( strcmp(it->name, currentSegmentInfo->fName) == 0 ) {
 
5261                                                         currentSegmentInfo->fInitProtection = it->init;
 
5262                                                         currentSegmentInfo->fMaxProtection = it->max;
 
5265                                         currentSegmentInfo->fBaseAddress = atom->getSegment().getBaseAddress();
 
5266                                         currentSegmentInfo->fFixedAddress = atom->getSegment().hasFixedAddress();
 
5267                                         if ( currentSegmentInfo->fFixedAddress && (&(atom->getSegment()) == &Segment::fgStackSegment) )
 
5268                                                 currentSegmentInfo->fIndependentAddress = true;
 
5269                                         this->fSegmentInfos.push_back(currentSegmentInfo);
 
5271                                 currentSectionInfo = new SectionInfo();
 
5272                                 currentSectionInfo->fAtoms.reserve(fAllAtoms->size()/4); // reduce reallocations by starting large
 
5273                                 strcpy(currentSectionInfo->fSectionName, atom->getSectionName());
 
5274                                 strcpy(currentSectionInfo->fSegmentName, atom->getSegment().getName());
 
5275                                 currentSectionInfo->fAlignment = atom->getAlignment().powerOf2;
 
5276                                 // check for -sectalign override
 
5277                                 std::vector<Options::SectionAlignment>& alignmentOverrides = fOptions.sectionAlignments();
 
5278                                 for(std::vector<Options::SectionAlignment>::iterator it=alignmentOverrides.begin(); it != alignmentOverrides.end(); ++it) {
 
5279                                         if ( (strcmp(it->segmentName, currentSectionInfo->fSegmentName) == 0) && (strcmp(it->sectionName, currentSectionInfo->fSectionName) == 0) )
 
5280                                                 currentSectionInfo->fAlignment = it->alignment;
 
5282                                 currentSectionInfo->fAllZeroFill = atom->isZeroFill();
 
5283                                 currentSectionInfo->fVirtualSection = ( currentSectionInfo->fSectionName[0] == '.');
 
5284                                 if ( !currentSectionInfo->fVirtualSection || fEmitVirtualSections )
 
5285                                         currentSectionInfo->setIndex(sectionIndex++);
 
5286                                 currentSegmentInfo->fSections.push_back(currentSectionInfo);
 
5288                         if ( (strcmp(currentSectionInfo->fSegmentName, "__TEXT") == 0) && (strcmp(currentSectionInfo->fSectionName, "._load_commands") == 0) ) {
 
5289                                 fLoadCommandsSection = currentSectionInfo;
 
5290                                 fLoadCommandsSegment = currentSegmentInfo;
 
5292                         if ( (strcmp(currentSectionInfo->fSegmentName, "__DATA") == 0) && (strcmp(currentSectionInfo->fSectionName, "__la_symbol_ptr") == 0) )
 
5293                                 currentSectionInfo->fAllLazyPointers = true;
 
5294                         if ( (strcmp(currentSectionInfo->fSegmentName, "__DATA") == 0) && (strcmp(currentSectionInfo->fSectionName, "__la_sym_ptr2") == 0) )
 
5295                                 currentSectionInfo->fAllLazyPointers = true;
 
5296                         if ( (strcmp(currentSectionInfo->fSegmentName, "__DATA") == 0) && (strcmp(currentSectionInfo->fSectionName, "__nl_symbol_ptr") == 0) )
 
5297                                 currentSectionInfo->fAllNonLazyPointers = true;
 
5298                         if ( (strcmp(currentSectionInfo->fSegmentName, "__IMPORT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__pointers") == 0) )
 
5299                                 currentSectionInfo->fAllNonLazyPointers = true;
 
5300                         if ( (fOptions.outputKind() == Options::kDyld) && (strcmp(currentSectionInfo->fSegmentName, "__DATA") == 0) && (strcmp(currentSectionInfo->fSectionName, "__pointers") == 0) )
 
5301                                 currentSectionInfo->fAllNonLazyPointers = true;
 
5302                         if ( (strcmp(currentSectionInfo->fSegmentName, "__TEXT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__picsymbolstub1") == 0) )
 
5303                                 currentSectionInfo->fAllStubs = true;
 
5304                         if ( (strcmp(currentSectionInfo->fSegmentName, "__TEXT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__symbol_stub1") == 0) )
 
5305                                 currentSectionInfo->fAllStubs = true;
 
5306                         if ( (strcmp(currentSectionInfo->fSegmentName, "__TEXT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__picsymbolstub2") == 0) )
 
5307                                 currentSectionInfo->fAllStubs = true;
 
5308                         if ( (strcmp(currentSectionInfo->fSegmentName, "__TEXT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__symbol_stub") == 0) )
 
5309                                 currentSectionInfo->fAllStubs = true;
 
5310                         if ( (strcmp(currentSectionInfo->fSegmentName, "__IMPORT") == 0) && (strcmp(currentSectionInfo->fSectionName, "__jump_table") == 0) ) {
 
5311                                 currentSectionInfo->fAllSelfModifyingStubs = true;
 
5312                                 currentSectionInfo->fAlignment = 6; // force x86 fast stubs to start on 64-byte boundary
 
5314                         curSection = atom->getSection();
 
5315                         if ( currentSectionInfo->fAllNonLazyPointers || currentSectionInfo->fAllLazyPointers 
 
5316                                 || currentSectionInfo->fAllStubs || currentSectionInfo->fAllStubs ) {
 
5317                                         fSymbolTableCommands->needDynamicTable();
 
5320                 // any non-zero fill atoms make whole section marked not-zero-fill
 
5321                 if ( currentSectionInfo->fAllZeroFill && ! atom->isZeroFill() )
 
5322                         currentSectionInfo->fAllZeroFill = false;
 
5323                 // change section object to be Writer's SectionInfo object
 
5324                 atom->setSection(currentSectionInfo);
 
5325                 // section alignment is that of a contained atom with the greatest alignment
 
5326                 uint8_t atomAlign = atom->getAlignment().powerOf2;
 
5327                 if ( currentSectionInfo->fAlignment < atomAlign ) 
 
5328                         currentSectionInfo->fAlignment = atomAlign;
 
5329                 // calculate section offset for this atom
 
5330                 uint64_t offset = currentSectionInfo->fSize;
 
5331                 uint64_t alignment = 1 << atomAlign;
 
5332                 uint64_t currentModulus = (offset % alignment);
 
5333                 uint64_t requiredModulus = atom->getAlignment().modulus;
 
5334                 if ( currentModulus != requiredModulus ) {
 
5335                         if ( requiredModulus > currentModulus )
 
5336                                 offset += requiredModulus-currentModulus;
 
5338                                 offset += requiredModulus+alignment-currentModulus;             
 
5340                 atom->setSectionOffset(offset);
 
5341                 uint64_t curAtomSize = atom->getSize();
 
5342                 currentSectionInfo->fSize = offset + curAtomSize;
 
5343                 // add atom to section vector
 
5344                 currentSectionInfo->fAtoms.push_back(atom);
 
5345                 // update largest size
 
5346                 if ( !currentSectionInfo->fAllZeroFill && (curAtomSize > fLargestAtomSize) )
 
5347                         fLargestAtomSize = curAtomSize;
 
5349         if ( (cstringSectionInfo != NULL) && (cstringSectionInfo->fAlignment > 0) ) {
 
5350                 // when merging cstring sections in .o files, all strings need to use the max alignment
 
5351                 uint64_t offset = 0;
 
5352                 uint64_t cstringAlignment = 1 << cstringSectionInfo->fAlignment;
 
5353                 for (std::vector<ObjectFile::Atom*>::iterator it=cstringSectionInfo->fAtoms.begin(); it != cstringSectionInfo->fAtoms.end(); it++) {
 
5354                         offset = (offset + (cstringAlignment-1)) & (-cstringAlignment);
 
5355                         ObjectFile::Atom* atom = *it;
 
5356                         atom->setSectionOffset(offset);
 
5357                         offset += atom->getSize();
 
5359                 cstringSectionInfo->fSize = offset;
 
5364 struct TargetAndOffset { ObjectFile::Atom* atom; uint32_t offset; };
 
5365 class TargetAndOffsetComparor
 
5368         bool operator()(const TargetAndOffset& left, const TargetAndOffset& right) const
 
5370                 if ( left.atom != right.atom )
 
5371                         return ( left.atom < right.atom );
 
5372                 return ( left.offset < right.offset );
 
5377 bool Writer<ppc>::addBranchIslands()
 
5379         return this->addPPCBranchIslands();
 
5383 bool Writer<ppc64>::addBranchIslands()
 
5385         return this->addPPCBranchIslands();
 
5389 bool Writer<x86>::addBranchIslands()
 
5391         // x86 branches can reach entire 4G address space, so no need for branch islands
 
5396 bool Writer<x86_64>::addBranchIslands()
 
5398         // x86 branches can reach entire 4G size of largest image
 
5404 bool Writer<ppc>::isBranch24Reference(uint8_t kind)
 
5407                 case ppc::kBranch24:
 
5408                 case ppc::kBranch24WeakImport:
 
5415 bool Writer<ppc64>::isBranch24Reference(uint8_t kind)
 
5418                 case ppc64::kBranch24:
 
5419                 case ppc64::kBranch24WeakImport:
 
5426 // PowerPC can do PC relative branches as far as +/-16MB.
 
5427 // If a branch target is >16MB then we insert one or more
 
5428 // "branch islands" between the branch and its target that
 
5429 // allows island hoping to the target.
 
5431 // Branch Island Algorithm
 
5433 // If the __TEXT segment < 16MB, then no branch islands needed
 
5434 // Otherwise, every 15MB into the __TEXT segment is region is
 
5435 // added which can contain branch islands.  Every out of range
 
5436 // bl instruction is checked.  If it crosses a region, an island
 
5437 // is added to that region with the same target and the bl is
 
5438 // adjusted to target the island instead.
 
5440 // In theory, if too many islands are added to one region, it
 
5441 // could grow the __TEXT enough that other previously in-range
 
5442 // bl branches could be pushed out of range.  We reduce the
 
5443 // probability this could happen by placing the ranges every
 
5444 // 15MB which means the region would have to be 1MB (256K islands)
 
5445 // before any branches could be pushed out of range.
 
5447 template <typename A>
 
5448 bool Writer<A>::addPPCBranchIslands()
 
5451         bool result = false;
 
5452         // Can only possibly need branch islands if __TEXT segment > 16M
 
5453         if ( fLoadCommandsSegment->fSize > 16000000 ) {
 
5454                 if ( log) fprintf(stderr, "ld: checking for branch islands, __TEXT segment size=%llu\n", fLoadCommandsSegment->fSize);
 
5455                 const uint32_t kBetweenRegions = 15*1024*1024; // place regions of islands every 15MB in __text section
 
5456                 SectionInfo* textSection = NULL;
 
5457                 for (std::vector<SectionInfo*>::iterator it=fLoadCommandsSegment->fSections.begin(); it != fLoadCommandsSegment->fSections.end(); it++) {
 
5458                         if ( strcmp((*it)->fSectionName, "__text") == 0 ) {
 
5460                                 if ( log) fprintf(stderr, "ld: checking for branch islands, __text section size=%llu\n", textSection->fSize);
 
5464                 const int kIslandRegionsCount = fLoadCommandsSegment->fSize / kBetweenRegions;
 
5465                 typedef std::map<TargetAndOffset,ObjectFile::Atom*, TargetAndOffsetComparor> AtomToIsland;
 
5466                 AtomToIsland regionsMap[kIslandRegionsCount];
 
5467                 std::vector<ObjectFile::Atom*> regionsIslands[kIslandRegionsCount];
 
5468                 unsigned int islandCount = 0;
 
5470                 // create islands for branch references that are out of range
 
5471                 for (std::vector<ObjectFile::Atom*>::iterator it=fAllAtoms->begin(); it != fAllAtoms->end(); it++) {
 
5472                         ObjectFile::Atom* atom = *it;
 
5473                         std::vector<ObjectFile::Reference*>&  references = atom->getReferences();
 
5474                         for (std::vector<ObjectFile::Reference*>::iterator rit=references.begin(); rit != references.end(); rit++) {
 
5475                                 ObjectFile::Reference* ref = *rit;
 
5476                                 if ( this->isBranch24Reference(ref->getKind()) ) {
 
5477                                         ObjectFile::Atom& target = ref->getTarget();
 
5478                                         int64_t srcAddr = atom->getAddress() + ref->getFixUpOffset();
 
5479                                         int64_t dstAddr = target.getAddress() + ref->getTargetOffset();
 
5480                                         int64_t displacement = dstAddr - srcAddr;
 
5481                                         TargetAndOffset finalTargetAndOffset = { &target, ref->getTargetOffset() };
 
5482                                         const int64_t kFifteenMegLimit = kBetweenRegions;
 
5483                                         if ( displacement > kFifteenMegLimit ) {
 
5484                                                 // create forward branch chain
 
5485                                                 ObjectFile::Atom* nextTarget = ⌖
 
5486                                                 uint64_t nextTargetOffset = ref->getTargetOffset();
 
5487                                                 for (int i=kIslandRegionsCount-1; i >=0 ; --i) {
 
5488                                                         AtomToIsland* region = ®ionsMap[i];
 
5489                                                         int64_t islandRegionAddr = kBetweenRegions * (i+1);
 
5490                                                         if ( (srcAddr < islandRegionAddr) && (islandRegionAddr <= dstAddr) ) {
 
5491                                                                 AtomToIsland::iterator pos = region->find(finalTargetAndOffset);
 
5492                                                                 if ( pos == region->end() ) {
 
5493                                                                         BranchIslandAtom<A>* island = new BranchIslandAtom<A>(*this, target.getDisplayName(), i, *nextTarget, nextTargetOffset);
 
5494                                                                         island->setSection(textSection);
 
5495                                                                         (*region)[finalTargetAndOffset] = island;
 
5496                                                                         if (log) fprintf(stderr, "added island %s to region %d for %s\n", island->getDisplayName(), i, atom->getDisplayName());
 
5497                                                                         regionsIslands[i].push_back(island);
 
5499                                                                         nextTarget = island;
 
5500                                                                         nextTargetOffset = 0;
 
5503                                                                         nextTarget = pos->second;
 
5504                                                                         nextTargetOffset = 0;
 
5508                                                 if (log) fprintf(stderr, "using island %s for %s\n", nextTarget->getDisplayName(), atom->getDisplayName());
 
5509                                                 ref->setTarget(*nextTarget, nextTargetOffset);
 
5511                                         else if ( displacement < (-kFifteenMegLimit) ) {
 
5512                                                 // create back branching chain
 
5513                                                 ObjectFile::Atom* prevTarget = ⌖
 
5514                                                 uint64_t prevTargetOffset = ref->getTargetOffset();
 
5515                                                 for (int i=0; i < kIslandRegionsCount ; ++i) {
 
5516                                                         AtomToIsland* region = ®ionsMap[i];
 
5517                                                         int64_t islandRegionAddr = kBetweenRegions * (i+1);
 
5518                                                         if ( (dstAddr <= islandRegionAddr) && (islandRegionAddr < srcAddr) ) {
 
5519                                                                 AtomToIsland::iterator pos = region->find(finalTargetAndOffset);
 
5520                                                                 if ( pos == region->end() ) {
 
5521                                                                         BranchIslandAtom<A>* island = new BranchIslandAtom<A>(*this, target.getDisplayName(), i, *prevTarget, prevTargetOffset);
 
5522                                                                         island->setSection(textSection);
 
5523                                                                         (*region)[finalTargetAndOffset] = island;
 
5524                                                                         if (log) fprintf(stderr, "added back island %s to region %d for %s\n", island->getDisplayName(), i, atom->getDisplayName());
 
5525                                                                         regionsIslands[i].push_back(island);
 
5527                                                                         prevTarget = island;
 
5528                                                                         prevTargetOffset = 0;
 
5531                                                                         prevTarget = pos->second;
 
5532                                                                         prevTargetOffset = 0;
 
5536                                                 if (log) fprintf(stderr, "using back island %s for %s\n", prevTarget->getDisplayName(), atom->getDisplayName());
 
5537                                                 ref->setTarget(*prevTarget, prevTargetOffset);
 
5543                 // insert islands into __text section and adjust section offsets
 
5544                 if ( islandCount > 0 ) {
 
5545                         if ( log ) fprintf(stderr, "ld: %u branch islands required in %u regions\n", islandCount, kIslandRegionsCount);
 
5546                         std::vector<ObjectFile::Atom*> newAtomList;
 
5547                         newAtomList.reserve(textSection->fAtoms.size()+islandCount);
 
5548                         uint64_t islandRegionAddr = kBetweenRegions;
 
5549                         uint64_t textSectionAlignment = (1 << textSection->fAlignment);
 
5550                         int regionIndex = 0;
 
5551                         uint64_t atomSlide = 0;
 
5552                         uint64_t sectionOffset = 0;
 
5553                         for (std::vector<ObjectFile::Atom*>::iterator it=textSection->fAtoms.begin(); it != textSection->fAtoms.end(); it++) {
 
5554                                 ObjectFile::Atom* atom = *it;
 
5555                                 newAtomList.push_back(atom);
 
5556                                 if ( atom->getAddress() > islandRegionAddr ) {
 
5557                                         uint64_t islandStartOffset = atom->getSectionOffset();
 
5558                                         sectionOffset = islandStartOffset + atomSlide;
 
5559                                         std::vector<ObjectFile::Atom*>* regionIslands = ®ionsIslands[regionIndex];
 
5560                                         for (std::vector<ObjectFile::Atom*>::iterator rit=regionIslands->begin(); rit != regionIslands->end(); rit++) {
 
5561                                                 ObjectFile::Atom* islandAtom = *rit;
 
5562                                                 newAtomList.push_back(islandAtom);
 
5563                                                 uint64_t alignment = 1 << (islandAtom->getAlignment().powerOf2);
 
5564                                                 sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
 
5565                                                 islandAtom->setSectionOffset(sectionOffset);
 
5566                                                 sectionOffset += islandAtom->getSize();
 
5569                                         islandRegionAddr += kBetweenRegions;
 
5570                                         uint64_t islandRegionAlignmentBlocks = (sectionOffset - islandStartOffset + textSectionAlignment - 1) / textSectionAlignment;
 
5571                                         atomSlide += (islandRegionAlignmentBlocks * textSectionAlignment);
 
5573                                 if ( atomSlide != 0 )
 
5574                                         atom->setSectionOffset(atom->getSectionOffset()+atomSlide);
 
5576                         sectionOffset = textSection->fSize+atomSlide;
 
5577                         // put any remaining islands at end of __text section
 
5578                         if ( regionIndex < kIslandRegionsCount ) {
 
5579                                 std::vector<ObjectFile::Atom*>* regionIslands = ®ionsIslands[regionIndex];
 
5580                                 for (std::vector<ObjectFile::Atom*>::iterator rit=regionIslands->begin(); rit != regionIslands->end(); rit++) {
 
5581                                         ObjectFile::Atom* islandAtom = *rit;
 
5582                                         newAtomList.push_back(islandAtom);
 
5583                                         uint64_t alignment = 1 << (islandAtom->getAlignment().powerOf2);
 
5584                                         sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
 
5585                                         islandAtom->setSectionOffset(sectionOffset);
 
5586                                         sectionOffset += islandAtom->getSize();
 
5590                         textSection->fAtoms = newAtomList;
 
5591                         textSection->fSize = sectionOffset;
 
5600 template <typename A>
 
5601 void Writer<A>::adjustLoadCommandsAndPadding()
 
5603         fSegmentCommands->computeSize();
 
5605         // recompute load command section offsets
 
5606         uint64_t offset = 0;
 
5607         std::vector<class ObjectFile::Atom*>& loadCommandAtoms = fLoadCommandsSection->fAtoms;
 
5608         const unsigned int atomCount = loadCommandAtoms.size();
 
5609         for (unsigned int i=0; i < atomCount; ++i) {
 
5610                 ObjectFile::Atom* atom = loadCommandAtoms[i];
 
5611                 uint64_t alignment = 1 << atom->getAlignment().powerOf2;
 
5612                 offset = ( (offset+alignment-1) & (-alignment) );
 
5613                 atom->setSectionOffset(offset);
 
5614                 uint32_t atomSize = atom->getSize();
 
5615                 if ( atomSize > fLargestAtomSize )
 
5616                         fLargestAtomSize = atomSize;
 
5618                 fLoadCommandsSection->fSize = offset;
 
5621         std::vector<SectionInfo*>& sectionInfos = fLoadCommandsSegment->fSections;
 
5622         const int sectionCount = sectionInfos.size();
 
5623         uint32_t totalSizeOfHeaderAndLoadCommands = 0;
 
5624         for(int j=0; j < sectionCount; ++j) {
 
5625                 SectionInfo* curSection = sectionInfos[j];
 
5626                 totalSizeOfHeaderAndLoadCommands += curSection->fSize;
 
5627                 if ( strcmp(curSection->fSectionName, fHeaderPadding->getSectionName()) == 0 )
 
5630         uint64_t paddingSize = 0;
 
5631         if ( fOptions.outputKind() == Options::kDyld ) {
 
5632                 // dyld itself has special padding requirements.  We want the beginning __text section to start at a stable address
 
5633                 paddingSize = 4096 - (totalSizeOfHeaderAndLoadCommands % 4096);
 
5635         else if ( fOptions.outputKind() == Options::kObjectFile ) {
 
5636                 // mach-o .o files need no padding between load commands and first section
 
5640                 // work backwards from end of segment and lay out sections so that extra room goes to padding atom
 
5642                 for(int j=sectionCount-1; j >=0; --j) {
 
5643                         SectionInfo* curSection = sectionInfos[j];
 
5644                         addr -= curSection->fSize;
 
5645                         addr = addr & (0 - (1 << curSection->fAlignment));
 
5646                         if ( strcmp(curSection->fSectionName, fHeaderPadding->getSectionName()) == 0 ) {
 
5647                                 addr -= totalSizeOfHeaderAndLoadCommands;
 
5648                                 paddingSize = addr % 4096;
 
5653                 // if command line requires more padding than this
 
5654                 uint32_t minPad = fOptions.minimumHeaderPad();
 
5655                 if ( fOptions.maxMminimumHeaderPad() ) {
 
5656                         // -headerpad_max_install_names means there should be room for every path load command to grow to 1204 bytes
 
5657                         uint32_t altMin = fLibraryToOrdinal.size() * MAXPATHLEN;
 
5658                         if ( fOptions.outputKind() ==  Options::kDynamicLibrary )
 
5659                                 altMin += MAXPATHLEN;
 
5660                         if ( altMin > minPad )
 
5663                 if ( paddingSize < minPad ) {
 
5664                         int extraPages = (minPad - paddingSize + 4095)/4096;
 
5665                         paddingSize += extraPages * 4096;
 
5669         // adjust atom size and update section size
 
5670         fHeaderPadding->setSize(paddingSize);
 
5671         for(int j=0; j < sectionCount; ++j) {
 
5672                 SectionInfo* curSection = sectionInfos[j];
 
5673                 if ( strcmp(curSection->fSectionName, fHeaderPadding->getSectionName()) == 0 )
 
5674                         curSection->fSize = paddingSize;
 
5678 // assign file offsets and logical address to all segments
 
5679 template <typename A>
 
5680 void Writer<A>::assignFileOffsets()
 
5682         bool finalLinkedImage = (fOptions.outputKind() != Options::kObjectFile);
 
5683         bool haveFixedSegments = false;
 
5684         uint64_t fileOffset = 0;
 
5685         uint64_t nextContiguousAddress = fOptions.baseAddress();
 
5686         uint64_t nextReadOnlyAddress = fOptions.baseAddress();
 
5687         uint64_t nextWritableAddress = fOptions.baseWritableAddress();
 
5689         // process segments with fixed addresses (-segaddr)
 
5690         for (std::vector<Options::SegmentStart>::iterator it = fOptions.customSegmentAddresses().begin(); it != fOptions.customSegmentAddresses().end(); ++it) {
 
5691                         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
5692                         SegmentInfo* curSegment = *segit;
 
5693                         if ( strcmp(curSegment->fName, it->name) == 0 ) {
 
5694                                 curSegment->fBaseAddress = it->address;
 
5695                                 curSegment->fFixedAddress = true;
 
5701         // Run through the segments and each segment's sections to assign addresses
 
5702         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
5703                 SegmentInfo* curSegment = *segit;
 
5705                 if ( fOptions.splitSeg() ) {
 
5706                         if ( curSegment->fInitProtection & VM_PROT_WRITE ) 
 
5707                                 nextContiguousAddress = nextWritableAddress;
 
5709                                 nextContiguousAddress = nextReadOnlyAddress;
 
5712                 fileOffset = (fileOffset+4095) & (-4096);
 
5713                 curSegment->fFileOffset = fileOffset;
 
5715                 // Set the segment base address
 
5716                 if ( curSegment->fFixedAddress )
 
5717                         haveFixedSegments = true;
 
5719                         curSegment->fBaseAddress = nextContiguousAddress;
 
5721                 // We've set the segment address, now run through each section.
 
5722                 uint64_t address = curSegment->fBaseAddress;
 
5723                 SectionInfo* firstZeroFillSection = NULL;
 
5724                 SectionInfo* prevSection = NULL;
 
5726                 std::vector<SectionInfo*>& sectionInfos = curSegment->fSections;
 
5728                 for (std::vector<SectionInfo*>::iterator it = sectionInfos.begin(); it != sectionInfos.end(); ++it) {
 
5729                         SectionInfo* curSection = *it;
 
5731                         // adjust section address based on alignment
 
5732                         uint64_t alignment = 1 << curSection->fAlignment;
 
5733                         address    = ( (address+alignment-1) & (-alignment) );
 
5735                         // adjust file offset to match address
 
5736                         if ( prevSection != NULL ) {
 
5737                                 if ( finalLinkedImage || !prevSection->fVirtualSection )
 
5738                                         fileOffset = (address - prevSection->getBaseAddress()) + prevSection->fFileOffset;
 
5740                                         fileOffset = ( (fileOffset+alignment-1) & (-alignment) );
 
5743                         // update section info
 
5744                         curSection->fFileOffset = fileOffset;
 
5745                         curSection->setBaseAddress(address);
 
5747                         // keep track of trailing zero fill sections
 
5748                         if ( curSection->fAllZeroFill && (firstZeroFillSection == NULL) )
 
5749                                 firstZeroFillSection = curSection;
 
5750                         if ( !curSection->fAllZeroFill && (firstZeroFillSection != NULL) && finalLinkedImage ) 
 
5751                                 throwf("zero-fill section %s not at end of segment", curSection->fSectionName);
 
5753                         // update running pointers
 
5754                         if ( finalLinkedImage || !curSection->fVirtualSection )
 
5755                                 address += curSection->fSize;
 
5756                         fileOffset += curSection->fSize;
 
5758                         // sanity check size of 32-bit binaries
 
5759                         if ( address > maxAddress() )
 
5760                                 throwf("section %s exceeds 4GB limit", curSection->fSectionName);
 
5762                         // update segment info
 
5763                         curSegment->fFileSize = fileOffset - curSegment->fFileOffset;
 
5764                         curSegment->fSize = curSegment->fFileSize;
 
5765                         prevSection = curSection;
 
5768                 if ( fOptions.outputKind() == Options::kObjectFile ) {
 
5769                         // don't page align .o files
 
5772                         // optimize trailing zero-fill sections to not occupy disk space
 
5773                         if ( firstZeroFillSection != NULL ) {
 
5774                                 curSegment->fFileSize = firstZeroFillSection->fFileOffset - curSegment->fFileOffset;
 
5775                                 fileOffset = firstZeroFillSection->fFileOffset;
 
5777                         // page align segment size
 
5778                         curSegment->fFileSize = (curSegment->fFileSize+4095) & (-4096);
 
5779                         curSegment->fSize         = (curSegment->fSize+4095) & (-4096);
 
5780                         if ( !curSegment->fIndependentAddress && (curSegment->fBaseAddress >= nextContiguousAddress) ) {
 
5781                                 nextContiguousAddress = (curSegment->fBaseAddress+curSegment->fSize+4095) & (-4096);
 
5782                                 if ( curSegment->fInitProtection & VM_PROT_WRITE )
 
5783                                         nextWritableAddress = nextContiguousAddress;
 
5785                                         nextReadOnlyAddress = nextContiguousAddress;
 
5790         // check for segment overlaps caused by user specified fixed segments (e.g. __PAGEZERO, __UNIXSTACK)
 
5791         if ( haveFixedSegments ) {
 
5792                 int segCount = fSegmentInfos.size();
 
5793                 for(int i=0; i < segCount; ++i) {
 
5794                         SegmentInfo* segment1 = fSegmentInfos[i];
 
5796                         for(int j=0; j < segCount; ++j) {
 
5798                                         SegmentInfo* segment2 = fSegmentInfos[j];
 
5800                                         if ( segment1->fBaseAddress < segment2->fBaseAddress ) {
 
5801                                                 if ( (segment1->fBaseAddress+segment1->fSize) > segment2->fBaseAddress )
 
5802                                                         throwf("segments overlap: %s (0x%08llX + 0x%08llX) and %s (0x%08llX + 0x%08llX)",
 
5803                                                                 segment1->fName, segment1->fBaseAddress, segment1->fSize, segment2->fName, segment2->fBaseAddress, segment2->fSize);
 
5805                                         else if ( segment1->fBaseAddress > segment2->fBaseAddress ) {
 
5806                                                 if ( (segment2->fBaseAddress+segment2->fSize) > segment1->fBaseAddress )
 
5807                                                         throwf("segments overlap: %s (0x%08llX + 0x%08llX) and %s (0x%08llX + 0x%08llX)",
 
5808                                                                 segment1->fName, segment1->fBaseAddress, segment1->fSize, segment2->fName, segment2->fBaseAddress, segment2->fSize);
 
5810                                         else if ( (segment1->fSize != 0) && (segment2->fSize != 0) ) {
 
5811                                                         throwf("segments overlap: %s (0x%08llX + 0x%08llX) and %s (0x%08llX + 0x%08llX)",
 
5812                                                                 segment1->fName, segment1->fBaseAddress, segment1->fSize, segment2->fName, segment2->fBaseAddress, segment2->fSize);
 
5819         // set up fFirstWritableSegment and fWritableSegmentPastFirst4GB
 
5820         for (std::vector<SegmentInfo*>::iterator segit = fSegmentInfos.begin(); segit != fSegmentInfos.end(); ++segit) {
 
5821                 SegmentInfo* curSegment = *segit;
 
5822                 if ( (curSegment->fInitProtection & VM_PROT_WRITE) != 0 ) {
 
5823                         if ( fFirstWritableSegment == NULL )
 
5824                                 fFirstWritableSegment = curSegment;
 
5825                         if ( (curSegment->fBaseAddress + curSegment->fSize - fOptions.baseAddress()) >= 0x100000000LL )
 
5826                                 fWritableSegmentPastFirst4GB = true;
 
5832 template <typename A>
 
5833 void Writer<A>::adjustLinkEditSections()
 
5835         // link edit content is always in last segment
 
5836         SegmentInfo* lastSeg = fSegmentInfos[fSegmentInfos.size()-1];
 
5837         unsigned int firstLinkEditSectionIndex = 0;
 
5838         while ( strcmp(lastSeg->fSections[firstLinkEditSectionIndex]->fSegmentName, "__LINKEDIT") != 0 )
 
5839                 ++firstLinkEditSectionIndex;
 
5841         const unsigned int linkEditSectionCount = lastSeg->fSections.size();
 
5842         uint64_t fileOffset = lastSeg->fSections[firstLinkEditSectionIndex]->fFileOffset;
 
5843         uint64_t address = lastSeg->fSections[firstLinkEditSectionIndex]->getBaseAddress();
 
5844         if ( fPadSegmentInfo != NULL ) {
 
5845                 // insert __4GBFILL segment into segments vector before LINKEDIT
 
5846                 for(std::vector<SegmentInfo*>::iterator it = fSegmentInfos.begin(); it != fSegmentInfos.end(); ++it) {
 
5847                         if ( *it == lastSeg ) {
 
5848                                 fSegmentInfos.insert(it, fPadSegmentInfo);
 
5852                 // adjust  __4GBFILL segment to span from end of last segment to zeroPageSize
 
5853                 fPadSegmentInfo->fSize = fOptions.zeroPageSize() - address;
 
5854                 fPadSegmentInfo->fBaseAddress = address;
 
5855                 // adjust LINKEDIT to start at zeroPageSize
 
5856                 address = fOptions.zeroPageSize();
 
5857                 lastSeg->fBaseAddress = fOptions.zeroPageSize();
 
5859         for (unsigned int i=firstLinkEditSectionIndex; i < linkEditSectionCount; ++i) {
 
5860                 std::vector<class ObjectFile::Atom*>& atoms = lastSeg->fSections[i]->fAtoms;
 
5861                 // adjust section address based on alignment
 
5862                 uint64_t sectionAlignment = 1 << lastSeg->fSections[i]->fAlignment;
 
5863                 uint64_t pad = ((address+sectionAlignment-1) & (-sectionAlignment)) - address;
 
5865                 fileOffset += pad;      // adjust file offset to match address
 
5866                 lastSeg->fSections[i]->setBaseAddress(address);
 
5867                 if ( strcmp(lastSeg->fSections[i]->fSectionName, "._absolute") == 0 )
 
5868                         lastSeg->fSections[i]->setBaseAddress(0);
 
5869                 lastSeg->fSections[i]->fFileOffset = fileOffset;
 
5870                 uint64_t sectionOffset = 0;
 
5871                 for (unsigned int j=0; j < atoms.size(); ++j) {
 
5872                         ObjectFile::Atom* atom = atoms[j];
 
5873                         uint64_t alignment = 1 << atom->getAlignment().powerOf2;
 
5874                         sectionOffset = ( (sectionOffset+alignment-1) & (-alignment) );
 
5875                         atom->setSectionOffset(sectionOffset);
 
5876                         uint64_t size = atom->getSize();
 
5877                         sectionOffset += size;
 
5878                         if ( size > fLargestAtomSize )
 
5879                                 fLargestAtomSize = size;
 
5881                 //fprintf(stderr, "setting: lastSeg->fSections[%d]->fSize = 0x%08llX\n", i, sectionOffset);
 
5882                 lastSeg->fSections[i]->fSize = sectionOffset;
 
5883                 fileOffset += sectionOffset;
 
5884                 address += sectionOffset;
 
5886         if ( fOptions.outputKind() == Options::kObjectFile ) {
 
5887                 //lastSeg->fBaseAddress = 0;
 
5888                 //lastSeg->fSize = lastSeg->fSections[firstLinkEditSectionIndex]->
 
5889                 //lastSeg->fFileOffset = 0;
 
5890                 //lastSeg->fFileSize =
 
5893                 lastSeg->fFileSize = fileOffset - lastSeg->fFileOffset;
 
5894                 lastSeg->fSize     = (address - lastSeg->fBaseAddress+4095) & (-4096);
 
5899 template <typename A>
 
5900 ObjectFile::Atom::Scope MachHeaderAtom<A>::getScope() const
 
5902         switch ( fWriter.fOptions.outputKind() ) {
 
5903                 case Options::kDynamicExecutable:
 
5904                 case Options::kStaticExecutable:
 
5905                         return ObjectFile::Atom::scopeGlobal;
 
5906                 case Options::kDynamicLibrary:
 
5907                 case Options::kDynamicBundle:
 
5908                 case Options::kDyld:
 
5909                 case Options::kObjectFile:
 
5910                         return ObjectFile::Atom::scopeLinkageUnit;
 
5912         throw "unknown header type";
 
5915 template <typename A>
 
5916 ObjectFile::Atom::SymbolTableInclusion MachHeaderAtom<A>::getSymbolTableInclusion() const
 
5918         switch ( fWriter.fOptions.outputKind() ) {
 
5919                 case Options::kDynamicExecutable:
 
5920                         return ObjectFile::Atom::kSymbolTableInAndNeverStrip;
 
5921                 case Options::kStaticExecutable:
 
5922                         return ObjectFile::Atom::kSymbolTableInAsAbsolute;
 
5923                 case Options::kDynamicLibrary:
 
5924                 case Options::kDynamicBundle:
 
5925                 case Options::kDyld:
 
5926                         return ObjectFile::Atom::kSymbolTableIn;
 
5927                 case Options::kObjectFile:
 
5928                         return ObjectFile::Atom::kSymbolTableNotIn;
 
5930         throw "unknown header type";
 
5933 template <typename A>
 
5934 const char* MachHeaderAtom<A>::getName() const
 
5936         switch ( fWriter.fOptions.outputKind() ) {
 
5937                 case Options::kDynamicExecutable:
 
5938                 case Options::kStaticExecutable:
 
5939                         return "__mh_execute_header";
 
5940                 case Options::kDynamicLibrary:
 
5941                         return "__mh_dylib_header";
 
5942                 case Options::kDynamicBundle:
 
5943                         return "__mh_bundle_header";
 
5944                 case Options::kObjectFile:
 
5946                 case Options::kDyld:
 
5947                         return "__mh_dylinker_header";
 
5949         throw "unknown header type";
 
5952 template <typename A>
 
5953 const char* MachHeaderAtom<A>::getDisplayName() const
 
5955         switch ( fWriter.fOptions.outputKind() ) {
 
5956                 case Options::kDynamicExecutable:
 
5957                 case Options::kStaticExecutable:
 
5958                 case Options::kDynamicLibrary:
 
5959                 case Options::kDynamicBundle:
 
5960                 case Options::kDyld:
 
5961                         return this->getName();
 
5962                 case Options::kObjectFile:
 
5963                         return "mach header";
 
5965         throw "unknown header type";
 
5968 template <typename A>
 
5969 void MachHeaderAtom<A>::copyRawContent(uint8_t buffer[]) const
 
5972         uint32_t fileType = 0;
 
5973         switch ( fWriter.fOptions.outputKind() ) {
 
5974                 case Options::kDynamicExecutable:
 
5975                 case Options::kStaticExecutable:
 
5976                         fileType = MH_EXECUTE;
 
5978                 case Options::kDynamicLibrary:
 
5979                         fileType = MH_DYLIB;
 
5981                 case Options::kDynamicBundle:
 
5982                         fileType = MH_BUNDLE;
 
5984                 case Options::kObjectFile:
 
5985                         fileType = MH_OBJECT;
 
5987                 case Options::kDyld:
 
5988                         fileType = MH_DYLINKER;
 
5994         if ( fWriter.fOptions.outputKind() == Options::kObjectFile ) {
 
5995                 if ( fWriter.fCanScatter )
 
5996                         flags = MH_SUBSECTIONS_VIA_SYMBOLS;
 
5999                 if ( fWriter.fOptions.outputKind() == Options::kStaticExecutable ) {
 
6000                         flags |= MH_NOUNDEFS;
 
6003                         flags = MH_DYLDLINK;
 
6004                         if ( fWriter.fOptions.bindAtLoad() )
 
6005                                 flags |= MH_BINDATLOAD;
 
6006                         switch ( fWriter.fOptions.nameSpace() ) {
 
6007                                 case Options::kTwoLevelNameSpace:
 
6008                                         flags |= MH_TWOLEVEL | MH_NOUNDEFS;
 
6010                                 case Options::kFlatNameSpace:
 
6012                                 case Options::kForceFlatNameSpace:
 
6013                                         flags |= MH_FORCE_FLAT;
 
6016                         if ( fWriter.fHasWeakExports )
 
6017                                 flags |= MH_WEAK_DEFINES;
 
6018                         if ( fWriter.fReferencesWeakImports || fWriter.fHasWeakExports )
 
6019                                 flags |= MH_BINDS_TO_WEAK;
 
6020                         if ( fWriter.fOptions.prebind() )
 
6021                                 flags |= MH_PREBOUND;
 
6022                         if ( fWriter.fOptions.splitSeg() )
 
6023                                 flags |= MH_SPLIT_SEGS;
 
6024                         if ( (fWriter.fOptions.outputKind() == Options::kDynamicLibrary) && fWriter.fNoReExportedDylibs ) 
 
6025                                 flags |= MH_NO_REEXPORTED_DYLIBS;
 
6026                         if ( fWriter.fOptions.positionIndependentExecutable() ) 
 
6029                 if ( fWriter.fOptions.hasExecutableStack() )
 
6030                         flags |= MH_ALLOW_STACK_EXECUTION;
 
6031                 if ( fWriter.fOptions.readerOptions().fRootSafe )
 
6032                         flags |= MH_ROOT_SAFE;
 
6033                 if ( fWriter.fOptions.readerOptions().fSetuidSafe )
 
6034                         flags |= MH_SETUID_SAFE;
 
6037         // get commands info
 
6038         uint32_t commandsSize = 0;
 
6039         uint32_t commandsCount = 0;
 
6041         std::vector<class ObjectFile::Atom*>& loadCommandAtoms = fWriter.fLoadCommandsSection->fAtoms;
 
6042         for (std::vector<ObjectFile::Atom*>::iterator it=loadCommandAtoms.begin(); it != loadCommandAtoms.end(); it++) {
 
6043                 ObjectFile::Atom* atom = *it;
 
6044                 commandsSize += atom->getSize();
 
6045                 // segment and symbol table atoms can contain more than one load command
 
6046                 if ( atom == fWriter.fSegmentCommands )
 
6047                         commandsCount += fWriter.fSegmentCommands->commandCount();
 
6048                 else if ( atom == fWriter.fSymbolTableCommands )
 
6049                         commandsCount += fWriter.fSymbolTableCommands->commandCount();
 
6050                 else if ( atom->getSize() != 0 )
 
6054         // fill out mach_header
 
6055         macho_header<typename A::P>* mh = (macho_header<typename A::P>*)buffer;
 
6057         mh->set_filetype(fileType);
 
6058         mh->set_ncmds(commandsCount);
 
6059         mh->set_sizeofcmds(commandsSize);
 
6060         mh->set_flags(flags);
 
6064 void MachHeaderAtom<ppc>::setHeaderInfo(macho_header<ppc::P>& header) const
 
6066         header.set_magic(MH_MAGIC);
 
6067         header.set_cputype(CPU_TYPE_POWERPC);
 
6068         switch ( fWriter.fCpuConstraint ) {
 
6069                 case ObjectFile::Reader::kCpuAny:
 
6070                         header.set_cpusubtype(CPU_SUBTYPE_POWERPC_ALL);
 
6072                 case ObjectFile::Reader::kCpuG3:
 
6073                         header.set_cpusubtype(CPU_SUBTYPE_POWERPC_750);
 
6075                 case ObjectFile::Reader::kCpuG4:
 
6076                         header.set_cpusubtype(CPU_SUBTYPE_POWERPC_7400);
 
6078                 case ObjectFile::Reader::kCpuG5:
 
6079                         header.set_cpusubtype(CPU_SUBTYPE_POWERPC_970);
 
6085 void MachHeaderAtom<ppc64>::setHeaderInfo(macho_header<ppc64::P>& header) const
 
6087         header.set_magic(MH_MAGIC_64);
 
6088         header.set_cputype(CPU_TYPE_POWERPC64);
 
6089         if ( (fWriter.fOptions.outputKind() == Options::kDynamicExecutable) && (fWriter.fOptions.macosxVersionMin() >= ObjectFile::ReaderOptions::k10_5) )
 
6090                 header.set_cpusubtype(CPU_SUBTYPE_POWERPC_ALL | 0x80000000);
 
6092                 header.set_cpusubtype(CPU_SUBTYPE_POWERPC_ALL);
 
6093         header.set_reserved(0);
 
6097 void MachHeaderAtom<x86>::setHeaderInfo(macho_header<x86::P>& header) const
 
6099         header.set_magic(MH_MAGIC);
 
6100         header.set_cputype(CPU_TYPE_I386);
 
6101         header.set_cpusubtype(CPU_SUBTYPE_I386_ALL);
 
6105 void MachHeaderAtom<x86_64>::setHeaderInfo(macho_header<x86_64::P>& header) const
 
6107         header.set_magic(MH_MAGIC_64);
 
6108         header.set_cputype(CPU_TYPE_X86_64);
 
6109         if ( (fWriter.fOptions.outputKind() == Options::kDynamicExecutable) && (fWriter.fOptions.macosxVersionMin() >= ObjectFile::ReaderOptions::k10_5) )
 
6110                 header.set_cpusubtype(CPU_SUBTYPE_X86_64_ALL | 0x80000000);
 
6112                 header.set_cpusubtype(CPU_SUBTYPE_X86_64_ALL);
 
6113         header.set_reserved(0);
 
6117 template <typename A>
 
6118 CustomStackAtom<A>::CustomStackAtom(Writer<A>& writer)
 
6119  : WriterAtom<A>(writer, Segment::fgStackSegment)
 
6121         if ( stackGrowsDown() )
 
6122                 Segment::fgStackSegment.setBaseAddress(writer.fOptions.customStackAddr() - writer.fOptions.customStackSize());
 
6124                 Segment::fgStackSegment.setBaseAddress(writer.fOptions.customStackAddr());
 
6129 bool CustomStackAtom<ppc>::stackGrowsDown()
 
6135 bool CustomStackAtom<ppc64>::stackGrowsDown()
 
6141 bool CustomStackAtom<x86>::stackGrowsDown()
 
6147 bool CustomStackAtom<x86_64>::stackGrowsDown()
 
6153 template <typename A>
 
6154 void SegmentLoadCommandsAtom<A>::computeSize()
 
6157         std::vector<SegmentInfo*>& segmentInfos = fWriter.fSegmentInfos;
 
6158         const int segCount = segmentInfos.size();
 
6159         for(int i=0; i < segCount; ++i) {
 
6160                 size += sizeof(macho_segment_command<P>);
 
6161                 std::vector<SectionInfo*>& sectionInfos = segmentInfos[i]->fSections;
 
6162                 const int sectionCount = sectionInfos.size();
 
6163                 for(int j=0; j < sectionCount; ++j) {
 
6164                         if ( fWriter.fEmitVirtualSections || ! sectionInfos[j]->fVirtualSection )
 
6165                                 size += sizeof(macho_section<P>);
 
6169         fCommandCount = segCount;
 
6170         if ( fWriter.fPadSegmentInfo != NULL ) {
 
6172                 fSize += sizeof(macho_segment_command<P>);
 
6177 uint64_t LoadCommandAtom<ppc>::alignedSize(uint64_t size)
 
6179         return ((size+3) & (-4));       // 4-byte align all load commands for 32-bit mach-o
 
6183 uint64_t LoadCommandAtom<ppc64>::alignedSize(uint64_t size)
 
6185         return ((size+7) & (-8));       // 8-byte align all load commands for 64-bit mach-o
 
6189 uint64_t LoadCommandAtom<x86>::alignedSize(uint64_t size)
 
6191         return ((size+3) & (-4));       // 4-byte align all load commands for 32-bit mach-o
 
6195 uint64_t LoadCommandAtom<x86_64>::alignedSize(uint64_t size)
 
6197         return ((size+7) & (-8));       // 8-byte align all load commands for 64-bit mach-o
 
6200 template <typename A>
 
6201 void SegmentLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6203         uint64_t size = this->getSize();
 
6204         const bool oneSegment =( fWriter.fOptions.outputKind() == Options::kObjectFile );
 
6205         bzero(buffer, size);
 
6206         uint8_t* p = buffer;
 
6207         typename std::vector<SegmentInfo*>& segmentInfos = fWriter.fSegmentInfos;
 
6208         const int segCount = segmentInfos.size();
 
6209         for(int i=0; i < segCount; ++i) {
 
6210                 SegmentInfo* segInfo = segmentInfos[i];
 
6211                 const int sectionCount = segInfo->fSections.size();
 
6212                 macho_segment_command<P>* cmd = (macho_segment_command<P>*)p;
 
6213                 cmd->set_cmd(macho_segment_command<P>::CMD);
 
6214                 cmd->set_segname(segInfo->fName);
 
6215                 cmd->set_vmaddr(segInfo->fBaseAddress);
 
6216                 cmd->set_vmsize(segInfo->fSize);
 
6217                 cmd->set_fileoff(segInfo->fFileOffset);
 
6218                 cmd->set_filesize(segInfo->fFileSize);
 
6219                 cmd->set_maxprot(segInfo->fMaxProtection);
 
6220                 cmd->set_initprot(segInfo->fInitProtection);
 
6221                 // add sections array
 
6222                 macho_section<P>* const sections = (macho_section<P>*)&p[sizeof(macho_segment_command<P>)];
 
6223                 unsigned int sectionsEmitted = 0;
 
6224                 for (int j=0; j < sectionCount; ++j) {
 
6225                         SectionInfo* sectInfo = segInfo->fSections[j];
 
6226                         if ( fWriter.fEmitVirtualSections || !sectInfo->fVirtualSection ) {
 
6227                                 macho_section<P>* sect = §ions[sectionsEmitted++];
 
6229                                         // .o file segment does not cover load commands, so recalc at first real section
 
6230                                         if ( sectionsEmitted == 1 ) {
 
6231                                                 cmd->set_vmaddr(sectInfo->getBaseAddress());
 
6232                                                 cmd->set_fileoff(sectInfo->fFileOffset);
 
6234                                         cmd->set_filesize((sectInfo->fFileOffset+sectInfo->fSize)-cmd->fileoff());
 
6235                                         cmd->set_vmsize(sectInfo->getBaseAddress() + sectInfo->fSize);
 
6237                                 sect->set_sectname(sectInfo->fSectionName);
 
6238                                 sect->set_segname(sectInfo->fSegmentName);
 
6239                                 sect->set_addr(sectInfo->getBaseAddress());
 
6240                                 sect->set_size(sectInfo->fSize);
 
6241                                 sect->set_offset(sectInfo->fFileOffset);
 
6242                                 sect->set_align(sectInfo->fAlignment);
 
6243                                 if ( sectInfo->fRelocCount != 0 ) {
 
6244                                         sect->set_reloff(sectInfo->fRelocOffset * sizeof(macho_relocation_info<P>) + fWriter.fSectionRelocationsAtom->getFileOffset());
 
6245                                         sect->set_nreloc(sectInfo->fRelocCount);
 
6247                                 if ( sectInfo->fAllZeroFill ) {
 
6248                                         sect->set_flags(S_ZEROFILL);
 
6249                                         sect->set_offset(0);
 
6251                                 else if ( sectInfo->fAllLazyPointers ) {
 
6252                                         sect->set_flags(S_LAZY_SYMBOL_POINTERS);
 
6253                                         sect->set_reserved1(sectInfo->fIndirectSymbolOffset);
 
6255                                 else if ( sectInfo->fAllNonLazyPointers ) {
 
6256                                         sect->set_flags(S_NON_LAZY_SYMBOL_POINTERS);
 
6257                                         sect->set_reserved1(sectInfo->fIndirectSymbolOffset);
 
6259                                 else if ( sectInfo->fAllStubs ) {
 
6260                                         sect->set_flags(S_SYMBOL_STUBS | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS);
 
6261                                         sect->set_reserved1(sectInfo->fIndirectSymbolOffset);
 
6262                                         sect->set_reserved2(sectInfo->fSize / sectInfo->fAtoms.size());
 
6264                                 else if ( sectInfo->fAllSelfModifyingStubs ) {
 
6265                                         sect->set_flags(S_SYMBOL_STUBS | S_ATTR_SELF_MODIFYING_CODE);
 
6266                                         sect->set_reserved1(sectInfo->fIndirectSymbolOffset);
 
6267                                         sect->set_reserved2(sectInfo->fSize / sectInfo->fAtoms.size());
 
6269                                 else if ( (strcmp(sectInfo->fSectionName, "__mod_init_func") == 0) && (strcmp(sectInfo->fSegmentName, "__DATA") == 0) ) {
 
6270                                         sect->set_flags(S_MOD_INIT_FUNC_POINTERS);
 
6272                                 else if ( (strcmp(sectInfo->fSectionName, "__mod_term_func") == 0) && (strcmp(sectInfo->fSegmentName, "__DATA") == 0) ) {
 
6273                                         sect->set_flags(S_MOD_TERM_FUNC_POINTERS);
 
6275                                 else if ( (strcmp(sectInfo->fSectionName, "__eh_frame") == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
6276                                         sect->set_flags(S_COALESCED | S_ATTR_NO_TOC | S_ATTR_STRIP_STATIC_SYMS);
 
6278                                 else if ( (strcmp(sectInfo->fSectionName, "__textcoal_nt") == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
6279                                         sect->set_flags(S_COALESCED);
 
6281                                 else if ( (strcmp(sectInfo->fSectionName, "__const_coal") == 0) && (strcmp(sectInfo->fSegmentName, "__DATA") == 0) ) {
 
6282                                         sect->set_flags(S_COALESCED);
 
6284                                 else if ( (strcmp(sectInfo->fSectionName, "__interpose") == 0) && (strcmp(sectInfo->fSegmentName, "__DATA") == 0) ) {
 
6285                                         sect->set_flags(S_INTERPOSING);
 
6287                                 else if ( (strcmp(sectInfo->fSectionName, "__cstring") == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
6288                                         sect->set_flags(S_CSTRING_LITERALS);
 
6290                                 else if ( (strcmp(sectInfo->fSectionName, "__literal4") == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
6291                                         sect->set_flags(S_4BYTE_LITERALS);
 
6293                                 else if ( (strcmp(sectInfo->fSectionName, "__literal8") == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
6294                                         sect->set_flags(S_8BYTE_LITERALS);
 
6296                                 else if ( (strcmp(sectInfo->fSectionName, "__literal16") == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
6297                                         sect->set_flags(S_16BYTE_LITERALS);
 
6299                                 else if ( (strcmp(sectInfo->fSectionName, "__message_refs") == 0) && (strcmp(sectInfo->fSegmentName, "__OBJC") == 0) ) {
 
6300                                         sect->set_flags(S_LITERAL_POINTERS);
 
6302                                 else if ( (strncmp(sectInfo->fSectionName, "__dof_", 6) == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
6303                                         sect->set_flags(S_DTRACE_DOF);
 
6305                                 else if ( (strncmp(sectInfo->fSectionName, "__dof_", 6) == 0) && (strcmp(sectInfo->fSegmentName, "__DATA") == 0) ) {
 
6306                                         sect->set_flags(S_DTRACE_DOF);
 
6308                                 else if ( (strncmp(sectInfo->fSectionName, "__text", 6) == 0) && (strcmp(sectInfo->fSegmentName, "__TEXT") == 0) ) {
 
6309                                         sect->set_flags(S_REGULAR | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS);
 
6313                 p = &p[sizeof(macho_segment_command<P>) + sectionsEmitted*sizeof(macho_section<P>)];
 
6314                 cmd->set_cmdsize(sizeof(macho_segment_command<P>) + sectionsEmitted*sizeof(macho_section<P>));
 
6315                 cmd->set_nsects(sectionsEmitted);
 
6320 template <typename A>
 
6321 SymbolTableLoadCommandsAtom<A>::SymbolTableLoadCommandsAtom(Writer<A>& writer)
 
6322  : LoadCommandAtom<A>(writer, Segment::fgTextSegment)
 
6324         bzero(&fSymbolTable, sizeof(macho_symtab_command<P>));
 
6325         bzero(&fDynamicSymbolTable, sizeof(macho_dysymtab_command<P>));
 
6326         switch ( fWriter.fOptions.outputKind() ) {
 
6327                 case Options::kDynamicExecutable:
 
6328                 case Options::kDynamicLibrary:
 
6329                 case Options::kDynamicBundle:
 
6330                 case Options::kDyld:
 
6331                         fNeedsDynamicSymbolTable = true;
 
6333                 case Options::kObjectFile:
 
6334                 case Options::kStaticExecutable:
 
6335                         fNeedsDynamicSymbolTable = false;
 
6338         writer.fSymbolTableCommands = this;
 
6343 template <typename A>
 
6344 void SymbolTableLoadCommandsAtom<A>::needDynamicTable() 
 
6346         fNeedsDynamicSymbolTable = true;
 
6350 template <typename A>
 
6351 uint64_t SymbolTableLoadCommandsAtom<A>::getSize() const
 
6353         if ( fNeedsDynamicSymbolTable )
 
6354                 return this->alignedSize(sizeof(macho_symtab_command<P>) + sizeof(macho_dysymtab_command<P>));
 
6356                 return this->alignedSize(sizeof(macho_symtab_command<P>));
 
6359 template <typename A>
 
6360 void SymbolTableLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6362         // build LC_DYSYMTAB command
 
6363         macho_symtab_command<P>*   symbolTableCmd = (macho_symtab_command<P>*)buffer;
 
6364         bzero(symbolTableCmd, sizeof(macho_symtab_command<P>));
 
6365         symbolTableCmd->set_cmd(LC_SYMTAB);
 
6366         symbolTableCmd->set_cmdsize(sizeof(macho_symtab_command<P>));
 
6367         symbolTableCmd->set_nsyms(fWriter.fSymbolTableCount);
 
6368         symbolTableCmd->set_symoff(fWriter.fSymbolTableAtom->getFileOffset());
 
6369         symbolTableCmd->set_stroff(fWriter.fStringsAtom->getFileOffset());
 
6370         symbolTableCmd->set_strsize(fWriter.fStringsAtom->getSize());
 
6372         // build LC_DYSYMTAB command
 
6373         if ( fNeedsDynamicSymbolTable ) {
 
6374                 macho_dysymtab_command<P>* dynamicSymbolTableCmd = (macho_dysymtab_command<P>*)&buffer[sizeof(macho_symtab_command<P>)];
 
6375                 bzero(dynamicSymbolTableCmd, sizeof(macho_dysymtab_command<P>));
 
6376                 dynamicSymbolTableCmd->set_cmd(LC_DYSYMTAB);
 
6377                 dynamicSymbolTableCmd->set_cmdsize(sizeof(macho_dysymtab_command<P>));
 
6378                 dynamicSymbolTableCmd->set_ilocalsym(fWriter.fSymbolTableStabsStartIndex);
 
6379                 dynamicSymbolTableCmd->set_nlocalsym(fWriter.fSymbolTableStabsCount + fWriter.fSymbolTableLocalCount);
 
6380                 dynamicSymbolTableCmd->set_iextdefsym(fWriter.fSymbolTableExportStartIndex);
 
6381                 dynamicSymbolTableCmd->set_nextdefsym(fWriter.fSymbolTableExportCount);
 
6382                 dynamicSymbolTableCmd->set_iundefsym(fWriter.fSymbolTableImportStartIndex);
 
6383                 dynamicSymbolTableCmd->set_nundefsym(fWriter.fSymbolTableImportCount);
 
6384                 if ( fWriter.fModuleInfoAtom != NULL ) {
 
6385                         dynamicSymbolTableCmd->set_tocoff(fWriter.fModuleInfoAtom->getTableOfContentsFileOffset());
 
6386                         dynamicSymbolTableCmd->set_ntoc(fWriter.fSymbolTableExportCount);
 
6387                         dynamicSymbolTableCmd->set_modtaboff(fWriter.fModuleInfoAtom->getModuleTableFileOffset());
 
6388                         dynamicSymbolTableCmd->set_nmodtab(1);
 
6389                         dynamicSymbolTableCmd->set_extrefsymoff(fWriter.fModuleInfoAtom->getReferencesFileOffset());
 
6390                         dynamicSymbolTableCmd->set_nextrefsyms(fWriter.fModuleInfoAtom->getReferencesCount());
 
6392                 dynamicSymbolTableCmd->set_indirectsymoff(fWriter.fIndirectTableAtom->getFileOffset());
 
6393                 dynamicSymbolTableCmd->set_nindirectsyms(fWriter.fIndirectTableAtom->fTable.size());
 
6394                 if ( fWriter.fOptions.outputKind() != Options::kObjectFile ) {
 
6395                         dynamicSymbolTableCmd->set_extreloff((fWriter.fExternalRelocs.size()==0) ? 0 : fWriter.fExternalRelocationsAtom->getFileOffset());
 
6396                         dynamicSymbolTableCmd->set_nextrel(fWriter.fExternalRelocs.size());
 
6397                         dynamicSymbolTableCmd->set_locreloff((fWriter.fInternalRelocs.size()==0) ? 0 : fWriter.fLocalRelocationsAtom->getFileOffset());
 
6398                         dynamicSymbolTableCmd->set_nlocrel(fWriter.fInternalRelocs.size());
 
6404 template <typename A>
 
6405 unsigned int SymbolTableLoadCommandsAtom<A>::commandCount()
 
6407         return fNeedsDynamicSymbolTable ? 2 : 1;
 
6410 template <typename A>
 
6411 uint64_t DyldLoadCommandsAtom<A>::getSize() const
 
6413         return this->alignedSize(sizeof(macho_dylinker_command<P>) + strlen("/usr/lib/dyld") + 1);
 
6416 template <typename A>
 
6417 void DyldLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6419         uint64_t size = this->getSize();
 
6420         bzero(buffer, size);
 
6421         macho_dylinker_command<P>* cmd = (macho_dylinker_command<P>*)buffer;
 
6422         if ( fWriter.fOptions.outputKind() == Options::kDyld )
 
6423                 cmd->set_cmd(LC_ID_DYLINKER);
 
6425                 cmd->set_cmd(LC_LOAD_DYLINKER);
 
6426         cmd->set_cmdsize(this->getSize());
 
6427         cmd->set_name_offset();
 
6428         strcpy((char*)&buffer[sizeof(macho_dylinker_command<P>)], "/usr/lib/dyld");
 
6431 template <typename A>
 
6432 uint64_t AllowableClientLoadCommandsAtom<A>::getSize() const
 
6434         return this->alignedSize(sizeof(macho_sub_client_command<P>) + strlen(this->clientString) + 1);
 
6437 template <typename A>
 
6438 void AllowableClientLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6440         uint64_t size = this->getSize();
 
6442         bzero(buffer, size);
 
6443         macho_sub_client_command<P>* cmd = (macho_sub_client_command<P>*)buffer;
 
6444         cmd->set_cmd(LC_SUB_CLIENT);
 
6445         cmd->set_cmdsize(size);
 
6446         cmd->set_client_offset();
 
6447         strcpy((char*)&buffer[sizeof(macho_sub_client_command<P>)], this->clientString);
 
6451 template <typename A>
 
6452 uint64_t DylibLoadCommandsAtom<A>::getSize() const
 
6454         if ( fOptimizedAway ) {
 
6458                 const char* path = fInfo.reader->getInstallPath();
 
6459                 return this->alignedSize(sizeof(macho_dylib_command<P>) + strlen(path) + 1);
 
6463 template <typename A>
 
6464 void DylibLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6466         if ( fOptimizedAway ) 
 
6468         uint64_t size = this->getSize();
 
6469         bzero(buffer, size);
 
6470         const char* path = fInfo.reader->getInstallPath();
 
6471         macho_dylib_command<P>* cmd = (macho_dylib_command<P>*)buffer;
 
6472         if ( fInfo.options.fWeakImport )
 
6473                 cmd->set_cmd(LC_LOAD_WEAK_DYLIB);
 
6474         else if ( fInfo.options.fReExport && (fWriter.fOptions.macosxVersionMin() >= ObjectFile::ReaderOptions::k10_5) )
 
6475                 cmd->set_cmd(LC_REEXPORT_DYLIB);
 
6477                 cmd->set_cmd(LC_LOAD_DYLIB);
 
6478         cmd->set_cmdsize(this->getSize());
 
6479         cmd->set_timestamp(2);  // needs to be some constant value that is different than DylibIDLoadCommandsAtom uses
 
6480         cmd->set_current_version(fInfo.reader->getCurrentVersion());
 
6481         cmd->set_compatibility_version(fInfo.reader->getCompatibilityVersion());
 
6482         cmd->set_name_offset();
 
6483         strcpy((char*)&buffer[sizeof(macho_dylib_command<P>)], path);
 
6488 template <typename A>
 
6489 uint64_t DylibIDLoadCommandsAtom<A>::getSize() const
 
6491         return this->alignedSize(sizeof(macho_dylib_command<P>) + strlen(fWriter.fOptions.installPath()) + 1);
 
6494 template <typename A>
 
6495 void DylibIDLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6497         uint64_t size = this->getSize();
 
6498         bzero(buffer, size);
 
6499         macho_dylib_command<P>* cmd = (macho_dylib_command<P>*)buffer;
 
6500         cmd->set_cmd(LC_ID_DYLIB);
 
6501         cmd->set_cmdsize(this->getSize());
 
6502         cmd->set_name_offset();
 
6503         cmd->set_timestamp(1);  // needs to be some constant value that is different than DylibLoadCommandsAtom uses
 
6504         cmd->set_current_version(fWriter.fOptions.currentVersion());
 
6505         cmd->set_compatibility_version(fWriter.fOptions.compatibilityVersion());
 
6506         strcpy((char*)&buffer[sizeof(macho_dylib_command<P>)], fWriter.fOptions.installPath());
 
6510 template <typename A>
 
6511 void RoutinesLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6513         uint64_t initAddr = fWriter.getAtomLoadAddress(fWriter.fEntryPoint);
 
6514         bzero(buffer, sizeof(macho_routines_command<P>));
 
6515         macho_routines_command<P>* cmd = (macho_routines_command<P>*)buffer;
 
6516         cmd->set_cmd(macho_routines_command<P>::CMD);
 
6517         cmd->set_cmdsize(this->getSize());
 
6518         cmd->set_init_address(initAddr);
 
6522 template <typename A>
 
6523 uint64_t SubUmbrellaLoadCommandsAtom<A>::getSize() const
 
6525         return this->alignedSize(sizeof(macho_sub_umbrella_command<P>) + strlen(fName) + 1);
 
6528 template <typename A>
 
6529 void SubUmbrellaLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6531         uint64_t size = this->getSize();
 
6532         bzero(buffer, size);
 
6533         macho_sub_umbrella_command<P>* cmd = (macho_sub_umbrella_command<P>*)buffer;
 
6534         cmd->set_cmd(LC_SUB_UMBRELLA);
 
6535         cmd->set_cmdsize(this->getSize());
 
6536         cmd->set_sub_umbrella_offset();
 
6537         strcpy((char*)&buffer[sizeof(macho_sub_umbrella_command<P>)], fName);
 
6540 template <typename A>
 
6541 void UUIDLoadCommandAtom<A>::generate() 
 
6543         switch ( fWriter.fOptions.getUUIDMode() ) {
 
6544                 case Options::kUUIDNone: 
 
6547                 case Options::kUUIDRandom:
 
6548                         ::uuid_generate_random(fUUID);
 
6551                 case Options::kUUIDContent: 
 
6558 template <typename A>
 
6559 void UUIDLoadCommandAtom<A>::setContent(const uint8_t uuid[16]) 
 
6561         memcpy(fUUID, uuid, 16);
 
6564 template <typename A>
 
6565 void UUIDLoadCommandAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6568                 uint64_t size = this->getSize();
 
6569                 bzero(buffer, size);
 
6570                 macho_uuid_command<P>* cmd = (macho_uuid_command<P>*)buffer;
 
6571                 cmd->set_cmd(LC_UUID);
 
6572                 cmd->set_cmdsize(this->getSize());
 
6573                 cmd->set_uuid((uint8_t*)fUUID);
 
6578 template <typename A>
 
6579 uint64_t SubLibraryLoadCommandsAtom<A>::getSize() const
 
6581         return this->alignedSize(sizeof(macho_sub_library_command<P>) + fNameLength + 1);
 
6584 template <typename A>
 
6585 void SubLibraryLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6587         uint64_t size = this->getSize();
 
6588         bzero(buffer, size);
 
6589         macho_sub_library_command<P>* cmd = (macho_sub_library_command<P>*)buffer;
 
6590         cmd->set_cmd(LC_SUB_LIBRARY);
 
6591         cmd->set_cmdsize(this->getSize());
 
6592         cmd->set_sub_library_offset();
 
6593         strncpy((char*)&buffer[sizeof(macho_sub_library_command<P>)], fNameStart, fNameLength);
 
6594         buffer[sizeof(macho_sub_library_command<P>)+fNameLength] = '\0';
 
6597 template <typename A>
 
6598 uint64_t UmbrellaLoadCommandsAtom<A>::getSize() const
 
6600         return this->alignedSize(sizeof(macho_sub_framework_command<P>) + strlen(fName) + 1);
 
6603 template <typename A>
 
6604 void UmbrellaLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6606         uint64_t size = this->getSize();
 
6607         bzero(buffer, size);
 
6608         macho_sub_framework_command<P>* cmd = (macho_sub_framework_command<P>*)buffer;
 
6609         cmd->set_cmd(LC_SUB_FRAMEWORK);
 
6610         cmd->set_cmdsize(this->getSize());
 
6611         cmd->set_umbrella_offset();
 
6612         strcpy((char*)&buffer[sizeof(macho_sub_framework_command<P>)], fName);
 
6616 uint64_t ThreadsLoadCommandsAtom<ppc>::getSize() const
 
6618         return this->alignedSize(16 + 40*4);    // base size + PPC_THREAD_STATE_COUNT * 4
 
6622 uint64_t ThreadsLoadCommandsAtom<ppc64>::getSize() const
 
6624         return this->alignedSize(16 + 76*4);    // base size + PPC_THREAD_STATE64_COUNT * 4
 
6628 uint64_t ThreadsLoadCommandsAtom<x86>::getSize() const
 
6630         return this->alignedSize(16 + 16*4);    // base size + i386_THREAD_STATE_COUNT * 4
 
6634 uint64_t ThreadsLoadCommandsAtom<x86_64>::getSize() const
 
6636         return this->alignedSize(16 + x86_THREAD_STATE64_COUNT * 4); 
 
6640 void ThreadsLoadCommandsAtom<ppc>::copyRawContent(uint8_t buffer[]) const
 
6642         uint64_t size = this->getSize();
 
6643         uint64_t start = fWriter.getAtomLoadAddress(fWriter.fEntryPoint);
 
6644         bzero(buffer, size);
 
6645         macho_thread_command<ppc::P>* cmd = (macho_thread_command<ppc::P>*)buffer;
 
6646         cmd->set_cmd(LC_UNIXTHREAD);
 
6647         cmd->set_cmdsize(size);
 
6648         cmd->set_flavor(1);                             // PPC_THREAD_STATE
 
6649         cmd->set_count(40);                             // PPC_THREAD_STATE_COUNT;
 
6650         cmd->set_thread_register(0, start);
 
6651         if ( fWriter.fOptions.hasCustomStack() )
 
6652                 cmd->set_thread_register(3, fWriter.fOptions.customStackAddr());        // r1
 
6657 void ThreadsLoadCommandsAtom<ppc64>::copyRawContent(uint8_t buffer[]) const
 
6659         uint64_t size = this->getSize();
 
6660         uint64_t start = fWriter.getAtomLoadAddress(fWriter.fEntryPoint);
 
6661         bzero(buffer, size);
 
6662         macho_thread_command<ppc64::P>* cmd = (macho_thread_command<ppc64::P>*)buffer;
 
6663         cmd->set_cmd(LC_UNIXTHREAD);
 
6664         cmd->set_cmdsize(size);
 
6665         cmd->set_flavor(5);                             // PPC_THREAD_STATE64
 
6666         cmd->set_count(76);                             // PPC_THREAD_STATE64_COUNT;
 
6667         cmd->set_thread_register(0, start);
 
6668         if ( fWriter.fOptions.hasCustomStack() )
 
6669                 cmd->set_thread_register(3, fWriter.fOptions.customStackAddr());        // r1
 
6673 void ThreadsLoadCommandsAtom<x86>::copyRawContent(uint8_t buffer[]) const
 
6675         uint64_t size = this->getSize();
 
6676         uint64_t start = fWriter.getAtomLoadAddress(fWriter.fEntryPoint);
 
6677         bzero(buffer, size);
 
6678         macho_thread_command<x86::P>* cmd = (macho_thread_command<x86::P>*)buffer;
 
6679         cmd->set_cmd(LC_UNIXTHREAD);
 
6680         cmd->set_cmdsize(size);
 
6681         cmd->set_flavor(1);                             // i386_THREAD_STATE
 
6682         cmd->set_count(16);                             // i386_THREAD_STATE_COUNT;
 
6683         cmd->set_thread_register(10, start);
 
6684         if ( fWriter.fOptions.hasCustomStack() )
 
6685                 cmd->set_thread_register(7, fWriter.fOptions.customStackAddr());        // esp
 
6690 void ThreadsLoadCommandsAtom<x86_64>::copyRawContent(uint8_t buffer[]) const
 
6692         uint64_t size = this->getSize();
 
6693         uint64_t start = fWriter.getAtomLoadAddress(fWriter.fEntryPoint);
 
6694         bzero(buffer, size);
 
6695         macho_thread_command<x86_64::P>* cmd = (macho_thread_command<x86_64::P>*)buffer;
 
6696         cmd->set_cmd(LC_UNIXTHREAD);
 
6697         cmd->set_cmdsize(size);
 
6698         cmd->set_flavor(x86_THREAD_STATE64);                    
 
6699         cmd->set_count(x86_THREAD_STATE64_COUNT);       
 
6700         cmd->set_thread_register(16, start);            // rip 
 
6701         if ( fWriter.fOptions.hasCustomStack() )
 
6702                 cmd->set_thread_register(7, fWriter.fOptions.customStackAddr());        // uesp
 
6706 template <typename A>
 
6707 uint64_t RPathLoadCommandsAtom<A>::getSize() const
 
6709         return this->alignedSize(sizeof(macho_rpath_command<P>) + strlen(fPath) + 1);
 
6712 template <typename A>
 
6713 void RPathLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6715         uint64_t size = this->getSize();
 
6716         bzero(buffer, size);
 
6717         macho_rpath_command<P>* cmd = (macho_rpath_command<P>*)buffer;
 
6718         cmd->set_cmd(LC_RPATH);
 
6719         cmd->set_cmdsize(this->getSize());
 
6720         cmd->set_path_offset();
 
6721         strcpy((char*)&buffer[sizeof(macho_rpath_command<P>)], fPath);
 
6725 template <typename A>
 
6726 void LoadCommandsPaddingAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6728         bzero(buffer, fSize);
 
6731 template <typename A>
 
6732 void LoadCommandsPaddingAtom<A>::setSize(uint64_t newSize) 
 
6735         // this resizing by-passes the way fLargestAtomSize is set, so re-check here
 
6736         if ( fWriter.fLargestAtomSize < newSize )
 
6737                 fWriter.fLargestAtomSize = newSize;
 
6740 template <typename A>
 
6741 uint64_t LinkEditAtom<A>::getFileOffset() const
 
6743         return ((SectionInfo*)this->getSection())->fFileOffset + this->getSectionOffset();
 
6747 template <typename A>
 
6748 uint64_t SectionRelocationsLinkEditAtom<A>::getSize() const
 
6750         return fWriter.fSectionRelocs.size() * sizeof(macho_relocation_info<P>);
 
6753 template <typename A>
 
6754 void SectionRelocationsLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6756         memcpy(buffer, &fWriter.fSectionRelocs[0], this->getSize());
 
6760 template <typename A>
 
6761 uint64_t LocalRelocationsLinkEditAtom<A>::getSize() const
 
6763         return fWriter.fInternalRelocs.size() * sizeof(macho_relocation_info<P>);
 
6766 template <typename A>
 
6767 void LocalRelocationsLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6769         memcpy(buffer, &fWriter.fInternalRelocs[0], this->getSize());
 
6774 template <typename A>
 
6775 uint64_t SymbolTableLinkEditAtom<A>::getSize() const
 
6777         return fWriter.fSymbolTableCount * sizeof(macho_nlist<P>);
 
6780 template <typename A>
 
6781 void SymbolTableLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6783         memcpy(buffer, fWriter.fSymbolTable, this->getSize());
 
6786 template <typename A>
 
6787 uint64_t ExternalRelocationsLinkEditAtom<A>::getSize() const
 
6789         return fWriter.fExternalRelocs.size() * sizeof(macho_relocation_info<P>);
 
6792 template <typename A>
 
6793 void ExternalRelocationsLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6795         std::sort(fWriter.fExternalRelocs.begin(), fWriter.fExternalRelocs.end(), ExternalRelocSorter<P>());
 
6796         memcpy(buffer, &fWriter.fExternalRelocs[0], this->getSize());
 
6801 template <typename A>
 
6802 uint64_t IndirectTableLinkEditAtom<A>::getSize() const
 
6804         return fTable.size() * sizeof(uint32_t);
 
6807 template <typename A>
 
6808 void IndirectTableLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6810         uint64_t size = this->getSize();
 
6811         bzero(buffer, size);
 
6812         const uint32_t indirectTableSize = fTable.size();
 
6813         uint32_t* indirectTable = (uint32_t*)buffer;
 
6814         for(std::vector<IndirectEntry>::const_iterator it = fTable.begin(); it != fTable.end(); ++it) {
 
6815                 if ( it->indirectIndex < indirectTableSize ) {
 
6816                         A::P::E::set32(indirectTable[it->indirectIndex], it->symbolIndex);
 
6819                         throwf("malformed indirect table. size=%d, index=%d", indirectTableSize, it->indirectIndex);
 
6826 template <typename A>
 
6827 uint64_t ModuleInfoLinkEditAtom<A>::getSize() const
 
6829         return fWriter.fSymbolTableExportCount*sizeof(macho_dylib_table_of_contents<P>) 
 
6830                         + sizeof(macho_dylib_module<P>) 
 
6831                         + this->getReferencesCount()*sizeof(uint32_t);
 
6834 template <typename A>
 
6835 uint32_t ModuleInfoLinkEditAtom<A>::getTableOfContentsFileOffset() const
 
6837         return this->getFileOffset();
 
6840 template <typename A>
 
6841 uint32_t ModuleInfoLinkEditAtom<A>::getModuleTableFileOffset() const
 
6843         return this->getFileOffset() + fWriter.fSymbolTableExportCount*sizeof(macho_dylib_table_of_contents<P>);
 
6846 template <typename A>
 
6847 uint32_t ModuleInfoLinkEditAtom<A>::getReferencesFileOffset() const
 
6849         return this->getModuleTableFileOffset() + sizeof(macho_dylib_module<P>);
 
6852 template <typename A>
 
6853 uint32_t ModuleInfoLinkEditAtom<A>::getReferencesCount() const
 
6855         return fWriter.fSymbolTableExportCount + fWriter.fSymbolTableImportCount;
 
6858 template <typename A>
 
6859 void ModuleInfoLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6861         uint64_t size = this->getSize();
 
6862         bzero(buffer, size);
 
6863         // create toc.  The symbols are already sorted, they are all in the smae module
 
6864         macho_dylib_table_of_contents<P>* p = (macho_dylib_table_of_contents<P>*)buffer;
 
6865         for(uint32_t i=0; i < fWriter.fSymbolTableExportCount; ++i, ++p) {
 
6866                 p->set_symbol_index(fWriter.fSymbolTableExportStartIndex+i);
 
6867                 p->set_module_index(0);
 
6869         // create module table (one entry)
 
6870         uint16_t numInits = 0;
 
6871         uint16_t numTerms = 0;
 
6872         std::vector<SegmentInfo*>& segmentInfos = fWriter.fSegmentInfos;
 
6873         for (std::vector<SegmentInfo*>::iterator segit = segmentInfos.begin(); segit != segmentInfos.end(); ++segit) {
 
6874                 if ( strcmp((*segit)->fName, "__DATA") == 0 ) {
 
6875                         std::vector<SectionInfo*>& sectionInfos = (*segit)->fSections;
 
6876                         for (std::vector<SectionInfo*>::iterator sectit = sectionInfos.begin(); sectit != sectionInfos.end(); ++sectit) {
 
6877                                 if ( strcmp((*sectit)->fSectionName, "__mod_init_func") == 0 ) 
 
6878                                         numInits = (*sectit)->fSize / sizeof(typename A::P::uint_t);
 
6879                                 else if ( strcmp((*sectit)->fSectionName, "__mod_term_func") == 0 ) 
 
6880                                         numTerms = (*sectit)->fSize / sizeof(typename A::P::uint_t);
 
6884         macho_dylib_module<P>* module = (macho_dylib_module<P>*)&buffer[fWriter.fSymbolTableExportCount*sizeof(macho_dylib_table_of_contents<P>)];
 
6885         module->set_module_name(fModuleNameOffset);
 
6886         module->set_iextdefsym(fWriter.fSymbolTableExportStartIndex);
 
6887         module->set_nextdefsym(fWriter.fSymbolTableExportCount);
 
6888         module->set_irefsym(0);
 
6889         module->set_nrefsym(this->getReferencesCount());
 
6890         module->set_ilocalsym(fWriter.fSymbolTableStabsStartIndex);
 
6891         module->set_nlocalsym(fWriter.fSymbolTableStabsCount+fWriter.fSymbolTableLocalCount);
 
6892         module->set_iextrel(0);
 
6893         module->set_nextrel(fWriter.fExternalRelocs.size());
 
6894         module->set_iinit_iterm(0,0);
 
6895         module->set_ninit_nterm(numInits,numTerms);
 
6896         module->set_objc_module_info_addr(0);   // Not used by ld_classic, and not used by objc runtime for many years
 
6897         module->set_objc_module_info_size(0);   // Not used by ld_classic, and not used by objc runtime for many years
 
6898         // create reference table
 
6899         macho_dylib_reference<P>* ref = (macho_dylib_reference<P>*)((uint8_t*)module + sizeof(macho_dylib_module<P>));
 
6900         for(uint32_t i=0; i < fWriter.fSymbolTableExportCount; ++i, ++ref) {
 
6901                 ref->set_isym(fWriter.fSymbolTableExportStartIndex+i);
 
6902                 ref->set_flags(REFERENCE_FLAG_DEFINED);
 
6904         for(uint32_t i=0; i < fWriter.fSymbolTableImportCount; ++i, ++ref) {
 
6905                 ref->set_isym(fWriter.fSymbolTableImportStartIndex+i);
 
6906                 std::map<const ObjectFile::Atom*,ObjectFile::Atom*>::iterator pos = fWriter.fStubsMap.find(fWriter.fImportedAtoms[i]);
 
6907                 if ( pos != fWriter.fStubsMap.end() )
 
6908                         ref->set_flags(REFERENCE_FLAG_UNDEFINED_LAZY);
 
6910                         ref->set_flags(REFERENCE_FLAG_UNDEFINED_NON_LAZY);
 
6916 template <typename A>
 
6917 StringsLinkEditAtom<A>::StringsLinkEditAtom(Writer<A>& writer)
 
6918         : LinkEditAtom<A>(writer), fCurrentBuffer(NULL), fCurrentBufferUsed(0)
 
6920         fCurrentBuffer = new char[kBufferSize];
 
6921         // burn first byte of string pool (so zero is never a valid string offset)
 
6922         fCurrentBuffer[fCurrentBufferUsed++] = ' ';
 
6923         // make offset 1 always point to an empty string
 
6924         fCurrentBuffer[fCurrentBufferUsed++] = '\0';
 
6927 template <typename A>
 
6928 uint64_t StringsLinkEditAtom<A>::getSize() const
 
6931         return (kBufferSize * fFullBuffers.size() + fCurrentBufferUsed + sizeof(typename A::P::uint_t) - 1) & (-sizeof(typename A::P::uint_t));
 
6934 template <typename A>
 
6935 void StringsLinkEditAtom<A>::copyRawContent(uint8_t buffer[]) const
 
6937         uint64_t offset = 0;
 
6938         for (unsigned int i=0; i < fFullBuffers.size(); ++i) {
 
6939                 memcpy(&buffer[offset], fFullBuffers[i], kBufferSize);
 
6940                 offset += kBufferSize;
 
6942         memcpy(&buffer[offset], fCurrentBuffer, fCurrentBufferUsed);
 
6943         // zero fill end to align
 
6944         offset += fCurrentBufferUsed;
 
6945         while ( (offset % sizeof(typename A::P::uint_t)) != 0 )
 
6946                 buffer[offset++] = 0;
 
6949 template <typename A>
 
6950 int32_t StringsLinkEditAtom<A>::add(const char* name)
 
6952         int32_t offset = kBufferSize * fFullBuffers.size() + fCurrentBufferUsed;
 
6953         int lenNeeded = strlcpy(&fCurrentBuffer[fCurrentBufferUsed], name, kBufferSize-fCurrentBufferUsed)+1;
 
6954         if ( (fCurrentBufferUsed+lenNeeded) < kBufferSize ) {
 
6955                 fCurrentBufferUsed += lenNeeded;
 
6958                 int copied = kBufferSize-fCurrentBufferUsed-1;
 
6959                 // change trailing '\0' that strlcpy added to real char
 
6960                 fCurrentBuffer[kBufferSize-1] = name[copied];
 
6961                 // alloc next buffer
 
6962                 fFullBuffers.push_back(fCurrentBuffer);
 
6963                 fCurrentBuffer = new char[kBufferSize];
 
6964                 fCurrentBufferUsed = 0;
 
6965                 // append rest of string
 
6966                 this->add(&name[copied+1]);
 
6972 template <typename A>
 
6973 int32_t StringsLinkEditAtom<A>::addUnique(const char* name)
 
6975         StringToOffset::iterator pos = fUniqueStrings.find(name);
 
6976         if ( pos != fUniqueStrings.end() ) {
 
6980                 int32_t offset = this->add(name);
 
6981                 fUniqueStrings[name] = offset;
 
6987 template <typename A>
 
6988 const char* StringsLinkEditAtom<A>::stringForIndex(int32_t index) const
 
6990         int32_t currentBufferStartIndex = kBufferSize * fFullBuffers.size();
 
6991         int32_t maxIndex = currentBufferStartIndex + fCurrentBufferUsed;
 
6992         // check for out of bounds
 
6993         if ( index > maxIndex )
 
6995         // check for index in fCurrentBuffer
 
6996         if ( index > currentBufferStartIndex )
 
6997                 return &fCurrentBuffer[index-currentBufferStartIndex];
 
6998         // otherwise index is in a full buffer
 
6999         uint32_t fullBufferIndex = index/kBufferSize;
 
7000         return &fFullBuffers[fullBufferIndex][index-(kBufferSize*fullBufferIndex)];
 
7005 template <typename A>
 
7006 BranchIslandAtom<A>::BranchIslandAtom(Writer<A>& writer, const char* name, int islandRegion, ObjectFile::Atom& target, uint32_t targetOffset)
 
7007  : WriterAtom<A>(writer, Segment::fgTextSegment), fTarget(target), fTargetOffset(targetOffset)
 
7009         char* buf = new char[strlen(name)+32];
 
7010         if ( targetOffset == 0 ) {
 
7011                 if ( islandRegion == 0 )
 
7012                         sprintf(buf, "%s$island", name);
 
7014                         sprintf(buf, "%s$island_%d", name, islandRegion);
 
7017                 sprintf(buf, "%s_plus_%d$island_%d", name, targetOffset, islandRegion);
 
7024 void BranchIslandAtom<ppc>::copyRawContent(uint8_t buffer[]) const
 
7026         int64_t displacement = fTarget.getAddress() + fTargetOffset - this->getAddress();
 
7027         int32_t branchInstruction = 0x48000000 | ((uint32_t)displacement & 0x03FFFFFC);
 
7028         OSWriteBigInt32(buffer, 0, branchInstruction);
 
7032 void BranchIslandAtom<ppc64>::copyRawContent(uint8_t buffer[]) const
 
7034         int64_t displacement = fTarget.getAddress() + fTargetOffset - this->getAddress();
 
7035         int32_t branchInstruction = 0x48000000 | ((uint32_t)displacement & 0x03FFFFFC);
 
7036         OSWriteBigInt32(buffer, 0, branchInstruction);
 
7040 uint64_t BranchIslandAtom<ppc>::getSize() const
 
7046 uint64_t BranchIslandAtom<ppc64>::getSize() const
 
7053 template <typename A>
 
7054 uint64_t SegmentSplitInfoLoadCommandsAtom<A>::getSize() const
 
7056         if ( fWriter.fSplitCodeToDataContentAtom->canEncode() )
 
7057                 return this->alignedSize(sizeof(macho_linkedit_data_command<P>));
 
7059                 return 0;       // a zero size causes the load command to be suppressed
 
7062 template <typename A>
 
7063 void SegmentSplitInfoLoadCommandsAtom<A>::copyRawContent(uint8_t buffer[]) const
 
7065         uint64_t size = this->getSize();
 
7066         bzero(buffer, size);
 
7067         macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)buffer;
 
7068         cmd->set_cmd(LC_SEGMENT_SPLIT_INFO);
 
7069         cmd->set_cmdsize(size);
 
7070         cmd->set_dataoff(fWriter.fSplitCodeToDataContentAtom->getFileOffset());
 
7071         cmd->set_datasize(fWriter.fSplitCodeToDataContentAtom->getSize());
 
7075 template <typename A>
 
7076 uint64_t SegmentSplitInfoContentAtom<A>::getSize() const
 
7078         return fEncodedData.size();
 
7081 template <typename A>
 
7082 void SegmentSplitInfoContentAtom<A>::copyRawContent(uint8_t buffer[]) const
 
7084         memcpy(buffer, &fEncodedData[0], fEncodedData.size());
 
7088 template <typename A>
 
7089 void SegmentSplitInfoContentAtom<A>::uleb128EncodeAddresses(const std::vector<SegmentSplitInfoContentAtom<A>::AtomAndOffset>& locations)
 
7091         pint_t addr = fWriter.fOptions.baseAddress();
 
7092         for(typename std::vector<AtomAndOffset>::const_iterator it = locations.begin(); it != locations.end(); ++it) {
 
7093                 pint_t nextAddr = it->atom->getAddress() + it->offset;
 
7094                 //fprintf(stderr, "\t0x%0llX\n", (uint64_t)nextAddr);
 
7095                 uint64_t delta = nextAddr - addr;
 
7097                         throw "double split seg info for same address";
 
7101                         byte = delta & 0x7F;
 
7105                         fEncodedData.push_back(byte);
 
7108                 while( byte >= 0x80 );
 
7113 template <typename A>
 
7114 void SegmentSplitInfoContentAtom<A>::encode()
 
7116         if ( ! fCantEncode ) {
 
7117                 fEncodedData.reserve(8192);
 
7119                 if ( fKind1Locations.size() != 0 ) {
 
7120                         fEncodedData.push_back(1);
 
7121                         //fprintf(stderr, "type 1:\n");
 
7122                         this->uleb128EncodeAddresses(fKind1Locations);
 
7123                         fEncodedData.push_back(0);
 
7126                 if ( fKind2Locations.size() != 0 ) {
 
7127                         fEncodedData.push_back(2);
 
7128                         //fprintf(stderr, "type 2:\n");
 
7129                         this->uleb128EncodeAddresses(fKind2Locations);
 
7130                         fEncodedData.push_back(0);
 
7133                 if ( fKind3Locations.size() != 0 ) {
 
7134                         fEncodedData.push_back(3);
 
7135                         //fprintf(stderr, "type 3:\n");
 
7136                         this->uleb128EncodeAddresses(fKind3Locations);
 
7137                         fEncodedData.push_back(0);
 
7140                 if ( fKind4Locations.size() != 0 ) {
 
7141                         fEncodedData.push_back(4);
 
7142                         //fprintf(stderr, "type 4:\n");
 
7143                         this->uleb128EncodeAddresses(fKind4Locations);
 
7144                         fEncodedData.push_back(0);
 
7147                 // always add zero byte to mark end
 
7148                 fEncodedData.push_back(0);
 
7150                 // add zeros to end to align size
 
7151                 while ( (fEncodedData.size() % sizeof(pint_t)) != 0 )
 
7152                         fEncodedData.push_back(0);
 
7157 template <typename A>
 
7158 ObjCInfoAtom<A>::ObjCInfoAtom(Writer<A>& writer, ObjectFile::Reader::ObjcConstraint objcConstraint, bool objcReplacementClasses)
 
7159         : WriterAtom<A>(writer, getInfoSegment())
 
7163         //      struct objc_image_info  {
 
7164         //              uint32_t        version;        // initially 0
 
7167         // #define OBJC_IMAGE_SUPPORTS_GC   2
 
7168         // #define OBJC_IMAGE_GC_ONLY       4
 
7170         if ( objcReplacementClasses ) 
 
7172         switch ( objcConstraint ) {
 
7173                 case ObjectFile::Reader::kObjcNone:
 
7174                 case ObjectFile::Reader::kObjcRetainRelease:
 
7176                 case ObjectFile::Reader::kObjcRetainReleaseOrGC:
 
7179                 case ObjectFile::Reader::kObjcGC:
 
7183         A::P::E::set32(fContent[1], value);
 
7186 template <typename A>
 
7187 void ObjCInfoAtom<A>::copyRawContent(uint8_t buffer[]) const
 
7189         memcpy(buffer, &fContent[0], 8);
 
7193 // objc info section is in a different segment and section for 32 vs 64 bit runtimes
 
7194 template <> const char* ObjCInfoAtom<ppc>::getSectionName()    const { return "__image_info"; }
 
7195 template <> const char* ObjCInfoAtom<x86>::getSectionName()    const { return "__image_info"; }
 
7196 template <> const char* ObjCInfoAtom<ppc64>::getSectionName()  const { return "__objc_imageinfo"; }
 
7197 template <> const char* ObjCInfoAtom<x86_64>::getSectionName() const { return "__objc_imageinfo"; }
 
7199 template <> Segment& ObjCInfoAtom<ppc>::getInfoSegment()    const { return Segment::fgObjCSegment; }
 
7200 template <> Segment& ObjCInfoAtom<x86>::getInfoSegment()    const { return Segment::fgObjCSegment; }
 
7201 template <> Segment& ObjCInfoAtom<ppc64>::getInfoSegment()  const { return Segment::fgDataSegment; }
 
7202 template <> Segment& ObjCInfoAtom<x86_64>::getInfoSegment() const { return Segment::fgDataSegment; }
 
7206 }; // namespace executable
 
7207 }; // namespace mach_o
 
7210 #endif // __EXECUTABLE_MACH_O__