2015-02-06 04:05:33 +08:00
|
|
|
//===------ lib/ReaderWriter/MachO/LayoutPass.h - Handles Layout of atoms -===//
|
2013-02-08 04:16:12 +08:00
|
|
|
//
|
|
|
|
// The LLVM Linker
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-02-06 04:05:33 +08:00
|
|
|
#ifndef LLD_READER_WRITER_MACHO_LAYOUT_PASS_H
|
|
|
|
#define LLD_READER_WRITER_MACHO_LAYOUT_PASS_H
|
2013-02-08 04:16:12 +08:00
|
|
|
|
|
|
|
#include "lld/Core/File.h"
|
|
|
|
#include "lld/Core/Pass.h"
|
2015-01-22 06:54:56 +08:00
|
|
|
#include "lld/Core/Reader.h"
|
2015-04-08 04:43:38 +08:00
|
|
|
#include "lld/Core/Simple.h"
|
2013-02-08 04:16:12 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include <map>
|
2013-10-18 10:56:31 +08:00
|
|
|
#include <string>
|
2013-02-08 04:16:12 +08:00
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
namespace lld {
|
|
|
|
class DefinedAtom;
|
2015-04-08 04:43:38 +08:00
|
|
|
class SimpleFile;
|
2013-02-08 04:16:12 +08:00
|
|
|
|
2015-02-06 04:05:33 +08:00
|
|
|
namespace mach_o {
|
|
|
|
|
2013-03-15 00:09:49 +08:00
|
|
|
/// This linker pass does the layout of the atoms. The pass is done after the
|
2013-02-08 04:16:12 +08:00
|
|
|
/// order their .o files were found on the command line, then by order of the
|
2013-12-02 07:51:36 +08:00
|
|
|
/// atoms (address) in the .o file. But some atoms have a preferred location
|
2013-02-08 04:16:12 +08:00
|
|
|
/// in their section (such as pinned to the start or end of the section), so
|
|
|
|
/// the sort must take that into account too.
|
|
|
|
class LayoutPass : public Pass {
|
|
|
|
public:
|
2013-12-08 11:12:08 +08:00
|
|
|
struct SortKey {
|
2016-03-23 01:15:50 +08:00
|
|
|
SortKey(OwningAtomPtr<DefinedAtom> &&atom,
|
|
|
|
const DefinedAtom *root, uint64_t override)
|
|
|
|
: _atom(std::move(atom)), _root(root), _override(override) {}
|
|
|
|
OwningAtomPtr<DefinedAtom> _atom;
|
2013-12-08 11:12:08 +08:00
|
|
|
const DefinedAtom *_root;
|
|
|
|
uint64_t _override;
|
2016-03-23 02:09:55 +08:00
|
|
|
|
|
|
|
// Note, these are only here to appease MSVC bots which didn't like
|
|
|
|
// the same methods being implemented/deleted in OwningAtomPtr.
|
|
|
|
SortKey(SortKey &&key) : _atom(std::move(key._atom)), _root(key._root),
|
|
|
|
_override(key._override) {
|
|
|
|
key._root = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
SortKey &operator=(SortKey &&key) {
|
|
|
|
_atom = std::move(key._atom);
|
|
|
|
_root = key._root;
|
|
|
|
key._root = nullptr;
|
|
|
|
_override = key._override;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
SortKey(const SortKey &) = delete;
|
|
|
|
void operator=(const SortKey&) = delete;
|
2013-02-08 04:16:12 +08:00
|
|
|
};
|
|
|
|
|
2014-11-08 05:01:21 +08:00
|
|
|
typedef std::function<bool (const DefinedAtom *left, const DefinedAtom *right,
|
|
|
|
bool &leftBeforeRight)> SortOverride;
|
|
|
|
|
2015-02-06 04:08:04 +08:00
|
|
|
LayoutPass(const Registry ®istry, SortOverride sorter);
|
2014-02-25 05:14:37 +08:00
|
|
|
|
2013-02-08 04:16:12 +08:00
|
|
|
/// Sorts atoms in mergedFile by content type then by command line order.
|
2016-03-31 04:36:31 +08:00
|
|
|
llvm::Error perform(SimpleFile &mergedFile) override;
|
2013-02-08 04:16:12 +08:00
|
|
|
|
2015-09-11 02:51:36 +08:00
|
|
|
~LayoutPass() override = default;
|
2013-02-08 04:16:12 +08:00
|
|
|
|
|
|
|
private:
|
2013-03-15 00:09:49 +08:00
|
|
|
// Build the followOn atoms chain as specified by the kindLayoutAfter
|
|
|
|
// reference type
|
2016-06-29 02:42:33 +08:00
|
|
|
void buildFollowOnTable(const File::AtomRange<DefinedAtom> &range);
|
2013-02-08 04:16:12 +08:00
|
|
|
|
2013-03-15 00:09:49 +08:00
|
|
|
// Build a map of Atoms to ordinals for sorting the atoms
|
2016-06-29 02:42:33 +08:00
|
|
|
void buildOrdinalOverrideMap(const File::AtomRange<DefinedAtom> &range);
|
2013-02-08 04:16:12 +08:00
|
|
|
|
2014-02-25 05:14:37 +08:00
|
|
|
const Registry &_registry;
|
2014-11-08 05:01:21 +08:00
|
|
|
SortOverride _customSorter;
|
2014-02-25 05:14:37 +08:00
|
|
|
|
2013-02-08 04:16:12 +08:00
|
|
|
typedef llvm::DenseMap<const DefinedAtom *, const DefinedAtom *> AtomToAtomT;
|
|
|
|
typedef llvm::DenseMap<const DefinedAtom *, uint64_t> AtomToOrdinalT;
|
2013-05-24 01:43:39 +08:00
|
|
|
|
|
|
|
// A map to be used to sort atoms. It represents the order of atoms in the
|
|
|
|
// result; if Atom X is mapped to atom Y in this map, X will be located
|
|
|
|
// immediately before Y in the output file. Y might be mapped to another
|
|
|
|
// atom, constructing a follow-on chain. An atom cannot be mapped to more
|
|
|
|
// than one atom unless all but one atom are of size zero.
|
2013-02-08 04:16:12 +08:00
|
|
|
AtomToAtomT _followOnNexts;
|
2013-05-24 01:43:39 +08:00
|
|
|
|
|
|
|
// A map to be used to sort atoms. It's a map from an atom to its root of
|
|
|
|
// follow-on chain. A root atom is mapped to itself. If an atom is not in
|
|
|
|
// _followOnNexts, the atom is not in this map, and vice versa.
|
2013-02-08 04:16:12 +08:00
|
|
|
AtomToAtomT _followOnRoots;
|
2013-05-24 01:43:39 +08:00
|
|
|
|
2013-02-08 04:16:12 +08:00
|
|
|
AtomToOrdinalT _ordinalOverrideMap;
|
2013-12-08 11:12:08 +08:00
|
|
|
|
2013-05-14 08:41:52 +08:00
|
|
|
// Helper methods for buildFollowOnTable().
|
|
|
|
const DefinedAtom *findAtomFollowedBy(const DefinedAtom *targetAtom);
|
|
|
|
bool checkAllPrevAtomsZeroSize(const DefinedAtom *targetAtom);
|
|
|
|
|
|
|
|
void setChainRoot(const DefinedAtom *targetAtom, const DefinedAtom *root);
|
Fix bug that CompareAtoms::compare is not transitive.
This patch fixes a bug in r190608. The results of a comparison function
passed to std::sort must be transitive, which is, if a < b and b < c, and if
a != b, a < c must be also true. CompareAtoms::compare did not actually
guarantee the transitivity. As a result the sort results were sometimes just
wrong.
Consider there are three atoms, X, Y, and Z, whose file ordinals are 1, 2, 3,
respectively. Z has a property "layout-after X". In this case, all the
following conditionals become true:
X < Y because X's ordinal is less than Y's
Y < Z because Y's ordinal is less than Z's
Z < X because of the layout-after relationship
This is not of course transitive. The reason why this happened is because
we used follow-on relationships for comparison if two atoms falls in the same
follow-on chain, but we used each atom's properties if they did not. This patch
fixes the issue by using follow-on root atoms for comparison to get consistent
results.
Differential Revision: http://llvm-reviews.chandlerc.com/D1980
llvm-svn: 193029
2013-10-19 11:18:18 +08:00
|
|
|
|
2016-06-29 02:42:33 +08:00
|
|
|
std::vector<SortKey> decorate(File::AtomRange<DefinedAtom> &atomRange) const;
|
2016-03-23 01:15:50 +08:00
|
|
|
|
2016-06-29 02:42:33 +08:00
|
|
|
void undecorate(File::AtomRange<DefinedAtom> &atomRange,
|
2013-12-08 11:12:08 +08:00
|
|
|
std::vector<SortKey> &keys) const;
|
|
|
|
|
Fix bug that CompareAtoms::compare is not transitive.
This patch fixes a bug in r190608. The results of a comparison function
passed to std::sort must be transitive, which is, if a < b and b < c, and if
a != b, a < c must be also true. CompareAtoms::compare did not actually
guarantee the transitivity. As a result the sort results were sometimes just
wrong.
Consider there are three atoms, X, Y, and Z, whose file ordinals are 1, 2, 3,
respectively. Z has a property "layout-after X". In this case, all the
following conditionals become true:
X < Y because X's ordinal is less than Y's
Y < Z because Y's ordinal is less than Z's
Z < X because of the layout-after relationship
This is not of course transitive. The reason why this happened is because
we used follow-on relationships for comparison if two atoms falls in the same
follow-on chain, but we used each atom's properties if they did not. This patch
fixes the issue by using follow-on root atoms for comparison to get consistent
results.
Differential Revision: http://llvm-reviews.chandlerc.com/D1980
llvm-svn: 193029
2013-10-19 11:18:18 +08:00
|
|
|
// Check if the follow-on graph is a correct structure. For debugging only.
|
2016-06-29 02:42:33 +08:00
|
|
|
void checkFollowonChain(const File::AtomRange<DefinedAtom> &range);
|
2013-02-08 04:16:12 +08:00
|
|
|
};
|
|
|
|
|
2015-02-06 04:05:33 +08:00
|
|
|
} // namespace mach_o
|
2013-02-08 04:16:12 +08:00
|
|
|
} // namespace lld
|
|
|
|
|
2015-02-06 04:05:33 +08:00
|
|
|
#endif // LLD_READER_WRITER_MACHO_LAYOUT_PASS_H
|