]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/passes/branch_island.cpp
ld64-264.3.102.tar.gz
[apple/ld64.git] / src / ld / passes / branch_island.cpp
index a8fb3252ae776479ed2d62d60df9228e3bc34336..65e3cf20d0a60e84e2a33d8cc1c943fa9d7e2cde 100644 (file)
@@ -389,7 +389,7 @@ static uint64_t maxDistanceBetweenIslands(const Options& opts, bool seenThumbBra
 //
 
 
-static void makeIslandsForSection(const Options& opts, ld::Internal& state, ld::Internal::FinalSection* textSection)
+static void makeIslandsForSection(const Options& opts, ld::Internal& state, ld::Internal::FinalSection* textSection, unsigned stubCount)
 {
        // assign section offsets to each atom in __text section, watch for thumb branches, and find total size
        bool hasThumbBranches = false;
@@ -448,7 +448,7 @@ static void makeIslandsForSection(const Options& opts, ld::Internal& state, ld::
                (const_cast<ld::Atom*>(atom))->setSectionOffset(offset);
                offset += atom->size();
        }
-       uint64_t totalTextSize = offset;
+       uint64_t totalTextSize = offset + stubCount*16;
        if ( (totalTextSize < textSizeWhenMightNeedBranchIslands(opts, hasThumbBranches)) && !haveCrossSectionBranches )
                return;
        if (_s_log) fprintf(stderr, "ld: section %s size=%llu, might need branch islands\n", textSection->sectionName(), totalTextSize);
@@ -552,7 +552,7 @@ static void makeIslandsForSection(const Options& opts, ld::Internal& state, ld::
                                if ( target->section().type() == ld::Section::typeStub )
                                        dstAddr = totalTextSize;
                                int64_t displacement = dstAddr - srcAddr;
-                               TargetAndOffset finalTargetAndOffset = { target, addend };
+                               TargetAndOffset finalTargetAndOffset = { target, (uint32_t)addend };
                                const int64_t kBranchLimit = kBetweenRegions;
                                if ( crossSectionBranch && ((displacement > kBranchLimit) || (displacement < (-kBranchLimit))) ) {
                                        const ld::Atom* island;
@@ -565,6 +565,7 @@ static void makeIslandsForSection(const Options& opts, ld::Internal& state, ld::
                                                                                                island, island->name(), displacement);
                                                ++islandCount;
                                                regionsIslands[0]->push_back(island);
+                                               state.atomToSection[island] = textSection;
                                        }
                                        else {
                                                island = pos->second;
@@ -588,6 +589,7 @@ static void makeIslandsForSection(const Options& opts, ld::Internal& state, ld::
                                                                (*region)[finalTargetAndOffset] = island;
                                                                if (_s_log) fprintf(stderr, "added forward branching island %p %s to region %d for %s\n", island, island->name(), i, atom->name());
                                                                regionsIslands[i]->push_back(island);
+                                                               state.atomToSection[island] = textSection;
                                                                ++islandCount;
                                                                nextTarget = island;
                                                        }
@@ -614,6 +616,7 @@ static void makeIslandsForSection(const Options& opts, ld::Internal& state, ld::
                                                                (*region)[finalTargetAndOffset] = island;
                                                                if (_s_log) fprintf(stderr, "added back branching island %p %s to region %d for %s\n", island, island->name(), i, atom->name());
                                                                regionsIslands[i]->push_back(island);
+                                                               state.atomToSection[island] = textSection;
                                                                ++islandCount;
                                                                prevTarget = island;
                                                        }
@@ -720,11 +723,19 @@ void doPass(const Options& opts, ld::Internal& state)
                buildAddressMap(opts, state);
        }
        
+       // scan sections for number of stubs
+       unsigned stubCount = 0;
+       for (std::vector<ld::Internal::FinalSection*>::iterator sit=state.sections.begin(); sit != state.sections.end(); ++sit) {
+               ld::Internal::FinalSection* sect = *sit;
+               if ( sect->type() == ld::Section::typeStub )
+                       stubCount = sect->atoms.size();
+       }
+
        // scan sections and add island to each code section
        for (std::vector<ld::Internal::FinalSection*>::iterator sit=state.sections.begin(); sit != state.sections.end(); ++sit) {
                ld::Internal::FinalSection* sect = *sit;
                if ( sect->type() == ld::Section::typeCode ) 
-                       makeIslandsForSection(opts, state, sect);
+                       makeIslandsForSection(opts, state, sect, stubCount);
        }
 }