]> git.saurik.com Git - apple/ld64.git/blobdiff - src/ld/passes/order.cpp
ld64-274.2.tar.gz
[apple/ld64.git] / src / ld / passes / order.cpp
index af73d66ecb4860f444964dd772704ee482bba465..a7d31f31618a77f910a4b67f416b3d6a18e0f0dd 100644 (file)
@@ -78,10 +78,11 @@ private:
 
        class Comparer {
        public:
-                                       Comparer(const Layout& l) : _layout(l) {}
+                                       Comparer(const Layout& l, ld::Internal& s) : _layout(l), _state(s) {}
                bool            operator()(const ld::Atom* left, const ld::Atom* right);
        private:
                const Layout&   _layout;
+               ld::Internal&   _state;
        };
                                
        typedef std::unordered_map<const char*, const ld::Atom*, CStringHash, CStringEquals> NameToAtom;
@@ -114,7 +115,7 @@ private:
 bool Layout::_s_log = false;
 
 Layout::Layout(const Options& opts, ld::Internal& state)
-       : _options(opts), _state(state), _comparer(*this), _haveOrderFile(opts.orderedSymbolsCount() != 0)
+       : _options(opts), _state(state), _comparer(*this, state), _haveOrderFile(opts.orderedSymbolsCount() != 0)
 {
 }
 
@@ -167,11 +168,21 @@ bool Layout::Comparer::operator()(const ld::Atom* left, const ld::Atom* right)
        bool leftIsAlias = left->isAlias();
        if ( leftIsAlias ) {
                for (ld::Fixup::iterator fit=left->fixupsBegin(); fit != left->fixupsEnd(); ++fit) {
+                       const ld::Atom* target = NULL;
                        if ( fit->kind == ld::Fixup::kindNoneFollowOn ) {
-                               assert(fit->binding == ld::Fixup::bindingDirectlyBound);
-                           if ( fit->u.target == right )
+                               switch ( fit->binding ) {
+                                       case ld::Fixup::bindingsIndirectlyBound:
+                                               target = _state.indirectBindingTable[fit->u.bindingIndex];
+                                               break;
+                                       case ld::Fixup::bindingDirectlyBound:
+                                               target = fit->u.target;
+                                               break;
+                    default:
+                        break;   
+                               }
+                           if ( target == right )
                                        return true; // left already before right
-                               left = fit->u.target; // sort as if alias was its target
+                               left = target; // sort as if alias was its target
                                break;
                    }
                }
@@ -179,11 +190,21 @@ bool Layout::Comparer::operator()(const ld::Atom* left, const ld::Atom* right)
        bool rightIsAlias = right->isAlias();
     if ( rightIsAlias ) {
         for (ld::Fixup::iterator fit=right->fixupsBegin(); fit != right->fixupsEnd(); ++fit) {
+                       const ld::Atom* target = NULL;
                        if ( fit->kind == ld::Fixup::kindNoneFollowOn ) {
-                               assert(fit->binding == ld::Fixup::bindingDirectlyBound);
-                if ( fit->u.target == left )
+                               switch ( fit->binding ) {
+                                       case ld::Fixup::bindingsIndirectlyBound:
+                                               target = _state.indirectBindingTable[fit->u.bindingIndex];
+                                               break;
+                                       case ld::Fixup::bindingDirectlyBound:
+                                               target = fit->u.target;
+                                               break;
+                    default:
+                        break;   
+                               }
+                           if ( target == left )
                     return false; // need to swap, alias is after target
-                               right = fit->u.target; // continue with sort as if right was target
+                               right = target; // continue with sort as if right was target
                 break;
                        }       
                }
@@ -489,8 +510,14 @@ void Layout::buildOrdinalOverrideMap()
                        switch ( atom->section().type() ) {
                                case ld::Section::typeZeroFill:
                                case ld::Section::typeTentativeDefs:
-                                       if ( atom->size() <= 512 ) 
-                                               moveToData.insert(atom);
+                                       if ( atom->size() <= 512 ) {
+                                               const char* dstSeg;
+                                               bool wildCardMatch;
+                                               const ld::File* f = atom->file();
+                                               const char* path = (f != NULL) ? f->path() : NULL;
+                                               if ( !_options.moveRwSymbol(atom->name(), path, dstSeg, wildCardMatch) )
+                                                       moveToData.insert(atom);
+                                       }
                                        break;
                                default:
                                        break;
@@ -531,22 +558,36 @@ void Layout::buildOrdinalOverrideMap()
                warning("only %u out of %lu order_file symbols were applicable", matchCount, _options.orderedSymbolsCount() );
        }
 
-
        // <rdar://problem/8612550> When order file used on data, turn ordered zero fill symbols into zeroed data
        if ( ! moveToData.empty() ) {
+               // <rdar://problem/14919139> only move zero fill symbols to __data if there is a __data section
+               ld::Internal::FinalSection* dataSect = NULL;
                for (std::vector<ld::Internal::FinalSection*>::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) {
                        ld::Internal::FinalSection* sect = *sit;
-                       switch ( sect->type() ) {
-                               case ld::Section::typeZeroFill:
-                               case ld::Section::typeTentativeDefs:
-                                       sect->atoms.erase(std::remove_if(sect->atoms.begin(), sect->atoms.end(), InSet(moveToData)), sect->atoms.end());
-                                       break;
-                               case ld::Section::typeUnclassified:
-                                       if ( (strcmp(sect->sectionName(), "__data") == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
-                                               sect->atoms.insert(sect->atoms.end(), moveToData.begin(), moveToData.end());
-                                       break;
-                               default:
-                                       break;
+                       if ( sect->type() == ld::Section::typeUnclassified ) {
+                               if ( (strcmp(sect->sectionName(), "__data") == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
+                                       dataSect = sect;
+                       }
+               }
+
+               if ( dataSect != NULL ) {
+                       // add atoms to __data
+                       dataSect->atoms.insert(dataSect->atoms.end(), moveToData.begin(), moveToData.end());
+                       // remove atoms from original sections
+                       for (std::vector<ld::Internal::FinalSection*>::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) {
+                               ld::Internal::FinalSection* sect = *sit;
+                               switch ( sect->type() ) {
+                                       case ld::Section::typeZeroFill:
+                                       case ld::Section::typeTentativeDefs:
+                                               sect->atoms.erase(std::remove_if(sect->atoms.begin(), sect->atoms.end(), InSet(moveToData)), sect->atoms.end());
+                                               break;
+                                       default:
+                                               break;
+                               }
+                       }
+                       // update atom-to-section map
+                       for (std::set<const ld::Atom*>::iterator it=moveToData.begin(); it != moveToData.end(); ++it) {
+                               _state.atomToSection[*it] = dataSect;
                        }
                }
        }
@@ -555,6 +596,18 @@ void Layout::buildOrdinalOverrideMap()
 
 void Layout::doPass()
 {
+       const bool log = false;
+       if ( log ) {
+               fprintf(stderr, "Unordered atoms:\n");
+               for (std::vector<ld::Internal::FinalSection*>::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) {
+                       ld::Internal::FinalSection* sect = *sit;
+                       for (std::vector<const ld::Atom*>::iterator ait=sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
+                               const ld::Atom* atom = *ait;
+                               fprintf(stderr, "\t%p\t%s\t%s\n", atom, sect->sectionName(), atom->name());
+                       }
+               }
+       }
+       
        // handle .o files that cannot have their atoms rearranged
        this->buildFollowOnTables();
 
@@ -564,19 +617,22 @@ void Layout::doPass()
        // sort atoms in each section
        for (std::vector<ld::Internal::FinalSection*>::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) {
                ld::Internal::FinalSection* sect = *sit;
-               //fprintf(stderr, "sorting section %s\n", sect->sectionName());
+               if ( sect->type() ==  ld::Section::typeTempAlias )
+                       continue;
+               if ( log ) fprintf(stderr, "sorting section %s\n", sect->sectionName());
                std::sort(sect->atoms.begin(), sect->atoms.end(), _comparer);
        }
 
-       //fprintf(stderr, "Sorted atoms:\n");
-       //for (std::vector<ld::Internal::FinalSection*>::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) {
-       //      ld::Internal::FinalSection* sect = *sit;
-       //      for (std::vector<const ld::Atom*>::iterator ait=sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
-       //              const ld::Atom* atom = *ait;
-       //              fprintf(stderr, "\t%p\t%s\t%s\n", atom, sect->sectionName(), atom->name());
-       //      }
-       //}
-
+       if ( log ) {
+               fprintf(stderr, "Sorted atoms:\n");
+               for (std::vector<ld::Internal::FinalSection*>::iterator sit=_state.sections.begin(); sit != _state.sections.end(); ++sit) {
+                       ld::Internal::FinalSection* sect = *sit;
+                       for (std::vector<const ld::Atom*>::iterator ait=sect->atoms.begin(); ait != sect->atoms.end(); ++ait) {
+                               const ld::Atom* atom = *ait;
+                               fprintf(stderr, "\t%p\t%s\t%s\n", atom, sect->sectionName(), atom->name());
+                       }
+               }
+       }
 }