#include <vector>
#include <map>
+#include <set>
+#include <unordered_map>
#include "ld.hpp"
#include "order.h"
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;
};
- class CStringEquals {
- public:
- bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
- };
- typedef __gnu_cxx::hash_map<const char*, const ld::Atom*, __gnu_cxx::hash<const char*>, CStringEquals> NameToAtom;
+ typedef std::unordered_map<const char*, const ld::Atom*, CStringHash, CStringEquals> NameToAtom;
typedef std::map<const ld::Atom*, const ld::Atom*> AtomToAtom;
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)
{
}
{
if ( left == right )
return false;
-
+
// magic section$start symbol always sorts to the start of its section
if ( left->contentType() == ld::Atom::typeSectionStart )
return true;
if ( right->contentType() == ld::Atom::typeSectionEnd )
return true;
+ // aliases sort before their target
+ 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 ) {
+ 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 = target; // sort as if alias was its target
+ break;
+ }
+ }
+ }
+ 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 ) {
+ 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 = target; // continue with sort as if right was target
+ break;
+ }
+ }
+ }
+
// the __common section can have real or tentative definitions
// we want the real ones to sort before tentative ones
bool leftIsTent = (left->definition() == ld::Atom::definitionTentative);
int64_t addrDiff = left->objectAddress() - right->objectAddress();
if ( addrDiff == 0 ) {
// have same address so one might be an alias, and aliases need to sort before target
- bool leftIsAlias = left->isAlias();
- bool rightIsAlias = right->isAlias();
if ( leftIsAlias != rightIsAlias )
return leftIsAlias;
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;
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;
}
}
}
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();
// 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;
+ 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%s\t%s\n", 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());
+ }
+ }
+ }
}