]> git.saurik.com Git - apple/ld64.git/commitdiff
ld64-242.2.tar.gz developer-tools-64 v242.2
authorApple <opensource@apple.com>
Tue, 5 May 2015 19:42:23 +0000 (19:42 +0000)
committerApple <opensource@apple.com>
Tue, 5 May 2015 19:42:23 +0000 (19:42 +0000)
src/ld/passes/branch_island.cpp
src/ld/passes/compact_unwind.cpp
src/ld/passes/got.cpp
unit-tests/test-cases/branch-islands/space.s

index 8efd10aaa0884fb06c9eda5e4b53403c28d6bf8d..a8fb3252ae776479ed2d62d60df9228e3bc34336 100644 (file)
@@ -61,6 +61,39 @@ static bool _s_log = false;
 static ld::Section _s_text_section("__TEXT", "__text", ld::Section::typeCode);
 
 
+#if SUPPORT_ARCH_arm64
+
+class ARM64BranchIslandAtom : public ld::Atom {
+public:
+                                                                                       ARM64BranchIslandAtom(const char* nm, const ld::Atom* target, TargetAndOffset finalTarget)
+                               : ld::Atom(_s_text_section, ld::Atom::definitionRegular, ld::Atom::combineNever,
+                                                       ld::Atom::scopeLinkageUnit, ld::Atom::typeBranchIsland, 
+                                                       ld::Atom::symbolTableIn, false, false, false, ld::Atom::Alignment(2)), 
+                               _name(nm),
+                               _fixup1(0, ld::Fixup::k1of1, ld::Fixup::kindStoreTargetAddressARM64Branch26, target),
+                               _fixup2(0, ld::Fixup::k1of1, ld::Fixup::kindIslandTarget, finalTarget.atom) {
+                                       if (_s_log) fprintf(stderr, "%p: ARM64 branch island to final target %s\n",
+                                                                               this, finalTarget.atom->name());
+                               }
+
+       virtual const ld::File*                                 file() const                                    { return NULL; }
+       virtual const char*                                             name() const                                    { return _name; }
+       virtual uint64_t                                                size() const                                    { return 4; }
+       virtual uint64_t                                                objectAddress() const                   { return 0; }
+       virtual void                                                    copyRawContent(uint8_t buffer[]) const {
+               OSWriteLittleInt32(buffer, 0, 0x14000000);
+       }
+       virtual void                                                    setScope(Scope)                                 { }
+       virtual ld::Fixup::iterator                             fixupsBegin() const                             { return (ld::Fixup*)&_fixup1; }
+       virtual ld::Fixup::iterator                             fixupsEnd()     const                           { return &((ld::Fixup*)&_fixup2)[1]; }
+
+private:
+       const char*                                                             _name;
+       ld::Fixup                                                               _fixup1;
+       ld::Fixup                                                               _fixup2;
+};
+#endif
+
 
 class ARMtoARMBranchIslandAtom : public ld::Atom {
 public:
@@ -274,6 +307,12 @@ static ld::Atom* makeBranchIsland(const Options& opts, ld::Fixup::Kind kind, int
                                return new ARMtoARMBranchIslandAtom(name, nextTarget, finalTarget);
                        }
                        break;
+#if SUPPORT_ARCH_arm64
+           case ld::Fixup::kindStoreARM64Branch26:
+               case ld::Fixup::kindStoreTargetAddressARM64Branch26:
+                       return new ARM64BranchIslandAtom(name, nextTarget, finalTarget);
+                       break;
+#endif
                default:
                        assert(0 && "unexpected branch kind");
                        break;
@@ -293,6 +332,11 @@ static uint64_t textSizeWhenMightNeedBranchIslands(const Options& opts, bool see
                        else
                                return  4000000;  // thumb1 can branch +/- 4MB
                        break;
+#if SUPPORT_ARCH_arm64
+               case CPU_TYPE_ARM64:
+                       return 128000000; // arm64 can branch +/- 128MB
+                       break;
+#endif
        }
        assert(0 && "unexpected architecture");
        return 0x100000000LL;
@@ -310,6 +354,11 @@ static uint64_t maxDistanceBetweenIslands(const Options& opts, bool seenThumbBra
                        else
                                return 3500000;                 // 0.5MB of branch islands per 4MB
                        break;
+#if SUPPORT_ARCH_arm64
+               case CPU_TYPE_ARM64:
+                       return 124*1024*1024;            // 4MB of branch islands per 128MB
+                       break;
+#endif
        }
        assert(0 && "unexpected architecture");
        return 0x100000000LL;
@@ -483,6 +532,10 @@ static void makeIslandsForSection(const Options& opts, ld::Internal& state, ld::
                                case ld::Fixup::kindStoreThumbBranch22:
                                case ld::Fixup::kindStoreTargetAddressARMBranch24:
                                case ld::Fixup::kindStoreTargetAddressThumbBranch22:
+#if SUPPORT_ARCH_arm64
+                               case ld::Fixup::kindStoreARM64Branch26:
+                               case ld::Fixup::kindStoreTargetAddressARM64Branch26:
+#endif
                                        haveBranch = true;
                                        break;
                 default:
@@ -652,9 +705,12 @@ void doPass(const Options& opts, ld::Internal& state)
        if ( !opts.allowBranchIslands() )
                return;
        
-       // only ARM needs branch islands
+       // only ARM[64] needs branch islands
        switch ( opts.architecture() ) {
                case CPU_TYPE_ARM:
+#if SUPPORT_ARCH_arm64
+               case CPU_TYPE_ARM64:
+#endif
                        break;
                default:
                        return;
index 6c1308d27c1e735974d8664c0e630e21abccd711..1d257ee268407042ebc6f94258da80e8343c6b58 100644 (file)
@@ -144,8 +144,7 @@ UnwindInfoAtom<A>::UnwindInfoAtom(const std::vector<UnwindEntry>& entries, uint6
        std::map<const ld::Atom*, uint32_t>     personalityIndexMap;
        makePersonalityIndexes(uniqueEntries, personalityIndexMap);
        if ( personalityIndexMap.size() > 3 ) {
-               warning("too many personality routines for compact unwind to encode");
-               return;
+               throw "too many personality routines for compact unwind to encode";
        }
 
        // put the most common encodings into the common table, but at most 127 of them
index 2b9da3a9816b99b68bc388d78155f20eddc951c2..66caf346cc9a05ed6e3035036c52b8e846ce0aa1 100644 (file)
@@ -161,10 +161,43 @@ void doPass(const Options& opts, ld::Internal& internal)
        if ( opts.outputKind() == Options::kObjectFile )
                return;
 
+       // pre-fill gotMap with existing non-lazy pointers
+       std::map<const ld::Atom*, const ld::Atom*> gotMap;
+       for (ld::Internal::FinalSection* sect : internal.sections) {
+               if ( sect->type() != ld::Section::typeNonLazyPointer )
+                       continue;
+               for (const ld::Atom* atom : sect->atoms) {
+                       const ld::Atom* target = NULL;
+                       for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
+                               switch (fit->kind) {
+                               case ld::Fixup::kindStoreTargetAddressLittleEndian64:
+                               case ld::Fixup::kindStoreTargetAddressLittleEndian32:
+                                       switch ( fit->binding ) {
+                                               case ld::Fixup::bindingsIndirectlyBound:
+                                                       target = internal.indirectBindingTable[fit->u.bindingIndex];
+                                                       break;
+                                               case ld::Fixup::bindingDirectlyBound:
+                                                       target = fit->u.target;
+                                                       break;
+                                               default:
+                                                       fprintf(stderr, "non-pointer is got entry\n");
+                                                       break;
+                                       }
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
+                       if ( target != NULL ) {
+                               if (log) fprintf(stderr, "found existing got entry to %s\n", target->name());
+                               gotMap[target] = atom;
+                       }
+               }
+       }
+
        // walk all atoms and fixups looking for GOT-able references
        // don't create GOT atoms during this loop because that could invalidate the sections iterator
        std::vector<const ld::Atom*> atomsReferencingGOT;
-       std::map<const ld::Atom*,ld::Atom*> gotMap;
        std::map<const ld::Atom*,bool>          weakImportMap;
        atomsReferencingGOT.reserve(128);
        for (std::vector<ld::Internal::FinalSection*>::iterator sit=internal.sections.begin(); sit != internal.sections.end(); ++sit) {
@@ -224,12 +257,13 @@ void doPass(const Options& opts, ld::Internal& internal)
                                }
                                else {
                                        // remember that we need to use GOT in this function
-                                       if ( log ) fprintf(stderr, "found GOT use in %s to %s\n", atom->name(), targetOfGOT->name());
+                                       if ( log ) fprintf(stderr, "found GOT use in %s\n", atom->name());
                                        if ( !atomUsesGOT ) {
                                                atomsReferencingGOT.push_back(atom);
                                                atomUsesGOT = true;
                                        }
-                                       gotMap[targetOfGOT] = NULL;
+                                       if ( gotMap.count(targetOfGOT) == 0 )
+                                               gotMap[targetOfGOT] = NULL;
                                        // record weak_import attribute
                                        std::map<const ld::Atom*,bool>::iterator pos = weakImportMap.find(targetOfGOT);
                                        if ( pos == weakImportMap.end() ) {
@@ -282,11 +316,15 @@ void doPass(const Options& opts, ld::Internal& internal)
 #endif
        }
        
-       // make GOT entries     
-       for (std::map<const ld::Atom*,ld::Atom*>::iterator it = gotMap.begin(); it != gotMap.end(); ++it) {
-               it->second = new GOTEntryAtom(internal, it->first, weakImportMap[it->first], is64);
+       // make GOT entries
+       for (auto& entry : gotMap) {
+               if ( entry.second == NULL ) {
+                       entry.second = new GOTEntryAtom(internal, entry.first, weakImportMap[entry.first], is64);
+                       if (log) fprintf(stderr, "making new GOT slot for %s, gotMap[%p] = %p\n", entry.first->name(), entry.first, entry.second);
+               }
        }
-       
+
+
        // update atoms to use GOT entries
        for (std::vector<const ld::Atom*>::iterator it=atomsReferencingGOT.begin(); it != atomsReferencingGOT.end(); ++it) {
                const ld::Atom* atom = *it;
@@ -318,6 +356,7 @@ void doPass(const Options& opts, ld::Internal& internal)
                                switch ( fitThatSetTarget->binding ) {
                                        case ld::Fixup::bindingsIndirectlyBound:
                                        case ld::Fixup::bindingDirectlyBound:
+                                               if ( log ) fprintf(stderr, "updating GOT use in %s to %s\n", atom->name(), targetOfGOT->name());
                                                fitThatSetTarget->binding = ld::Fixup::bindingDirectlyBound;
                                                fitThatSetTarget->u.target = gotMap[targetOfGOT];
                                                break;
index a15a2c2bd87323fa38b5b3824a75f2fb87a7d8e5..18ceb96584022b941ef4cbd898d51ce7de844238 100644 (file)
@@ -73,4 +73,25 @@ _space4:
     .space 2*1024*1024
 #endif
 
+
+#if __arm64__
+
+    .text
+    .align 4
+_prejunk:
+    nop
+    nop
+
+       // arm64 branches are +/- 128MB
+_space1:
+    .space 120*1024*1024
+_space2:
+    .space 120*1024*1024
+_space3:
+    .space 120*1024*1024
+
+
+#endif
+
+
     .subsections_via_symbols