X-Git-Url: https://git.saurik.com/apple/ld64.git/blobdiff_plain/afe874b1634377ecb27057ee76deb04915bb34d7..f80fe69f3f29962e8aa43a99f8ed9201548f3d78:/src/ld/passes/branch_island.cpp diff --git a/src/ld/passes/branch_island.cpp b/src/ld/passes/branch_island.cpp index 99b3eb8..96b6d35 100644 --- a/src/ld/passes/branch_island.cpp +++ b/src/ld/passes/branch_island.cpp @@ -59,42 +59,6 @@ public: static bool _s_log = false; static ld::Section _s_text_section("__TEXT", "__text", ld::Section::typeCode); -class PPCBranchIslandAtom : public ld::Atom { -public: - PPCBranchIslandAtom(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), - _target(target), - _finalTarget(finalTarget) { } - - virtual const ld::File* file() const { return NULL; } - virtual bool translationUnitSource(const char** dir, const char**) const - { return false; } - 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 { - int64_t displacement = _target->finalAddress() - this->finalAddress(); - const int64_t bl_sixteenMegLimit = 0x00FFFFFF; - if ( _target->contentType() == ld::Atom::typeBranchIsland ) { - // try optimizing away intermediate islands - int64_t skipToFinalDisplacement = _finalTarget.atom->finalAddress() + _finalTarget.offset - this->finalAddress(); - if ( (skipToFinalDisplacement > bl_sixteenMegLimit) && (skipToFinalDisplacement < (-bl_sixteenMegLimit)) ) { - displacement = skipToFinalDisplacement; - } - } - int32_t branchInstruction = 0x48000000 | ((uint32_t)displacement & 0x03FFFFFC); - OSWriteBigInt32(buffer, 0, branchInstruction); - } - virtual void setScope(Scope) { } - -private: - const char* _name; - const ld::Atom* _target; - TargetAndOffset _finalTarget; -}; class ARMtoARMBranchIslandAtom : public ld::Atom { @@ -108,8 +72,6 @@ public: _finalTarget(finalTarget) { } virtual const ld::File* file() const { return NULL; } - virtual bool translationUnitSource(const char** dir, const char**) const - { return false; } virtual const char* name() const { return _name; } virtual uint64_t size() const { return 4; } virtual uint64_t objectAddress() const { return 0; } @@ -158,8 +120,6 @@ public: _finalTarget(finalTarget) { } virtual const ld::File* file() const { return NULL; } - virtual bool translationUnitSource(const char** dir, const char**) const - { return false; } virtual const char* name() const { return _name; } virtual uint64_t size() const { return 16; } virtual uint64_t objectAddress() const { return 0; } @@ -198,8 +158,6 @@ public: _finalTarget(finalTarget) { } virtual const ld::File* file() const { return NULL; } - virtual bool translationUnitSource(const char** dir, const char**) const - { return false; } virtual const char* name() const { return _name; } virtual uint64_t size() const { return 4; } virtual uint64_t objectAddress() const { return 0; } @@ -263,8 +221,6 @@ public: _finalTarget(finalTarget) { } virtual const ld::File* file() const { return NULL; } - virtual bool translationUnitSource(const char** dir, const char**) const - { return false; } virtual const char* name() const { return _name; } virtual uint64_t size() const { return 8; } virtual uint64_t objectAddress() const { return 0; } @@ -303,10 +259,6 @@ static ld::Atom* makeBranchIsland(const Options& opts, ld::Fixup::Kind kind, int } switch ( kind ) { - case ld::Fixup::kindStorePPCBranch24: - case ld::Fixup::kindStoreTargetAddressPPCBranch24: - return new PPCBranchIslandAtom(name, nextTarget, finalTarget); - break; case ld::Fixup::kindStoreARMBranch24: case ld::Fixup::kindStoreThumbBranch22: case ld::Fixup::kindStoreTargetAddressARMBranch24: @@ -337,10 +289,6 @@ static ld::Atom* makeBranchIsland(const Options& opts, ld::Fixup::Kind kind, int static uint64_t textSizeWhenMightNeedBranchIslands(const Options& opts, bool seenThumbBranch) { switch ( opts.architecture() ) { - case CPU_TYPE_POWERPC: - case CPU_TYPE_POWERPC64: - return 16000000; - break; case CPU_TYPE_ARM: if ( ! seenThumbBranch ) return 32000000; // ARM can branch +/- 32MB @@ -358,10 +306,6 @@ static uint64_t textSizeWhenMightNeedBranchIslands(const Options& opts, bool see static uint64_t maxDistanceBetweenIslands(const Options& opts, bool seenThumbBranch) { switch ( opts.architecture() ) { - case CPU_TYPE_POWERPC: - case CPU_TYPE_POWERPC64: - return 14*1024*1024; - break; case CPU_TYPE_ARM: if ( ! seenThumbBranch ) return 30*1024*1024; // 2MB of branch islands per 32MB @@ -405,10 +349,8 @@ void doPass(const Options& opts, ld::Internal& state) if ( opts.outputKind() == Options::kObjectFile ) return; - // only PowerPC and ARM need branch islands + // only ARM needs branch islands switch ( opts.architecture() ) { - case CPU_TYPE_POWERPC: - case CPU_TYPE_POWERPC64: case CPU_TYPE_ARM: break; default: @@ -462,9 +404,45 @@ void doPass(const Options& opts, ld::Internal& state) return; if (_s_log) fprintf(stderr, "ld: __text section size=%llu, might need branch islands\n", totalTextSize); - // figure out how many regions of branch islands will be needed - const uint32_t kBetweenRegions = maxDistanceBetweenIslands(opts, hasThumbBranches); // place regions of islands every 14MB in __text section - const int kIslandRegionsCount = totalTextSize / kBetweenRegions; + // Figure out how many regions of branch islands will be needed, and their locations. + // Construct a vector containing the atoms after which branch islands will be inserted, + // taking into account follow on fixups. No atom run without an island can exceed kBetweenRegions. + const uint64_t kBetweenRegions = maxDistanceBetweenIslands(opts, hasThumbBranches); // place regions of islands every 14MB in __text section + std::vector branchIslandInsertionPoints; // atoms in the atom list after which branch islands will be inserted + uint64_t previousIslandEndAddr = 0; + const ld::Atom *insertionPoint; + branchIslandInsertionPoints.reserve(totalTextSize/kBetweenRegions*2); + for (std::vector::iterator it=textSection->atoms.begin(); it != textSection->atoms.end(); it++) { + const ld::Atom* atom = *it; + // if we move past the next atom, will the run length exceed kBetweenRegions? + if ( atom->sectionOffset() + atom->size() - previousIslandEndAddr > kBetweenRegions ) { + // yes. Add the last known good location (atom) for inserting a branch island. + if ( insertionPoint == NULL ) + throwf("Unable to insert branch island. No insertion point available."); + branchIslandInsertionPoints.push_back(insertionPoint); + previousIslandEndAddr = insertionPoint->sectionOffset()+insertionPoint->size(); + insertionPoint = NULL; + } + // Can we insert an island after this atom? If so then keep track of it. + if ( !atom->hasFixupsOfKind(ld::Fixup::kindNoneFollowOn) ) + insertionPoint = atom; + } + // add one more island after the last atom + if (insertionPoint != NULL) + branchIslandInsertionPoints.push_back(insertionPoint); + const int kIslandRegionsCount = branchIslandInsertionPoints.size(); + if (_s_log) { + fprintf(stderr, "ld: will use %u branch island regions\n", kIslandRegionsCount); + for (std::vector::iterator it = branchIslandInsertionPoints.begin(); it != branchIslandInsertionPoints.end(); ++it) { + const ld::Atom* atom = *it; + const ld::File *file = atom->file(); + fprintf(stderr, "ld: branch island will be inserted at 0x%llx after %s", atom->sectionOffset()+atom->size(), atom->name()); + if (file) fprintf(stderr, " (%s)", atom->file()->path()); + fprintf(stderr, "\n"); + } + } + + typedef std::map AtomToIsland; AtomToIsland* regionsMap[kIslandRegionsCount]; std::vector* regionsIslands[kIslandRegionsCount]; @@ -473,7 +451,6 @@ void doPass(const Options& opts, ld::Internal& state) regionsIslands[i] = new std::vector(); } unsigned int islandCount = 0; - if (_s_log) fprintf(stderr, "ld: will use %u branch island regions\n", kIslandRegionsCount); // create islands for branches in __text that are out of range for (std::vector::iterator ait=textSection->atoms.begin(); ait != textSection->atoms.end(); ++ait) { @@ -506,8 +483,6 @@ void doPass(const Options& opts, ld::Internal& state) case ld::Fixup::kindAddAddend: addend = fit->u.addend; break; - case ld::Fixup::kindStorePPCBranch24: - case ld::Fixup::kindStoreTargetAddressPPCBranch24: case ld::Fixup::kindStoreARMBranch24: case ld::Fixup::kindStoreThumbBranch22: case ld::Fixup::kindStoreTargetAddressARMBranch24: @@ -585,30 +560,25 @@ void doPass(const Options& opts, ld::Internal& state) if ( _s_log ) fprintf(stderr, "ld: %u branch islands required in %u regions\n", islandCount, kIslandRegionsCount); std::vector newAtomList; newAtomList.reserve(textSection->atoms.size()+islandCount); - uint64_t islandRegionAddr = kBetweenRegions;; - int regionIndex = 0; - for (std::vector::iterator it=textSection->atoms.begin(); it != textSection->atoms.end(); it++) { - const ld::Atom* atom = *it; - if ( (atom->sectionOffset()+atom->size()) > islandRegionAddr ) { - std::vector* regionIslands = regionsIslands[regionIndex]; - for (std::vector::iterator rit=regionIslands->begin(); rit != regionIslands->end(); rit++) { - const ld::Atom* islandAtom = *rit; - newAtomList.push_back(islandAtom); - if ( _s_log ) fprintf(stderr, "inserting island %s into __text section\n", islandAtom->name()); - } - ++regionIndex; - islandRegionAddr += kBetweenRegions; + + uint64_t regionIndex = 0; + for (std::vector::iterator ait=textSection->atoms.begin(); ait != textSection->atoms.end(); ait++) { + newAtomList.push_back(*ait); + // copy over atoms until we find an island insertion point + // Note that the last insertion point is the last atom, so this loop never moves the iterator to atoms.end(). + while (*ait != branchIslandInsertionPoints[regionIndex]) { + ait++; + newAtomList.push_back(*ait); } - newAtomList.push_back(atom); - } - // put any remaining islands at end of __text section - if ( regionIndex < kIslandRegionsCount ) { + + // insert the branch island atoms after the insertion point atom std::vector* regionIslands = regionsIslands[regionIndex]; for (std::vector::iterator rit=regionIslands->begin(); rit != regionIslands->end(); rit++) { const ld::Atom* islandAtom = *rit; newAtomList.push_back(islandAtom); if ( _s_log ) fprintf(stderr, "inserting island %s into __text section\n", islandAtom->name()); } + regionIndex++; } // swap in new list of atoms for __text section textSection->atoms.clear();