Update MCLinker to work with LLVM 3.4.
This corresponds to merging upstream MCLinker with the following SHA:
6dcbf36cdb146d6f175ba2f18a9004753cafeaff
Change-Id: I1bc8c2ce4accc563450bc71ee295a6e47a0c0469
diff --git a/include/mcld/ADT/BinTree.h b/include/mcld/ADT/BinTree.h
index 76de607..4093b72 100644
--- a/include/mcld/ADT/BinTree.h
+++ b/include/mcld/ADT/BinTree.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_BINARY_TREE_H
-#define MCLD_BINARY_TREE_H
+#ifndef MCLD_ADT_BITREE_H
+#define MCLD_ADT_BITREE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -438,16 +438,16 @@
// @param DIRECT the direction of the connecting edge of the parent node.
// @param position the parent node
// @param value the value being pushed.
- template<size_t DIRECT, class Pos>
- BinaryTree& join(Pos position, const DataType& value) {
+ template<size_t DIRECT>
+ BinaryTree& join(TreeIteratorBase& pPosition, const DataType& pValue) {
node_type *node = BinaryTreeBase<DataType>::createNode();
- node->data = const_cast<DataType*>(&value);
- if (position.isRoot())
- proxy::hook<TreeIteratorBase::Leftward>(position.m_pNode,
- const_cast<const node_type*>(node));
+ node->data = const_cast<DataType*>(&pValue);
+
+ if (pPosition.isRoot())
+ pPosition.hook<TreeIteratorBase::Leftward>(node);
else
- proxy::hook<DIRECT>(position.m_pNode,
- const_cast<const node_type*>(node));
+ pPosition.hook<DIRECT>(node);
+
return *this;
}
@@ -456,14 +456,13 @@
// @param position the parent node
// @param the tree being joined.
// @return the joined tree
- template<size_t DIRECT, class Pos>
- BinaryTree& merge(Pos position, BinaryTree& pTree) {
+ template<size_t DIRECT>
+ BinaryTree& merge(TreeIteratorBase& pPosition, BinaryTree& pTree) {
if (this == &pTree)
return *this;
if (!pTree.empty()) {
- proxy::hook<DIRECT>(position.m_pNode,
- const_cast<const NodeBase*>(pTree.m_Root.node.left));
+ pPosition.hook<DIRECT>(pTree.m_Root.node.left);
BinaryTreeBase<DataType>::m_Root.summon(
pTree.BinaryTreeBase<DataType>::m_Root);
BinaryTreeBase<DataType>::m_Root.delegate(pTree.m_Root);
diff --git a/include/mcld/ADT/Flags.h b/include/mcld/ADT/Flags.h
index d38d941..c6a41e8 100644
--- a/include/mcld/ADT/Flags.h
+++ b/include/mcld/ADT/Flags.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_FLAGS_H
-#define MCLD_FLAGS_H
+#ifndef MCLD_ADT_FLAGS_H
+#define MCLD_ADT_FLAGS_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/ADT/GraphLite/Digraph.h b/include/mcld/ADT/GraphLite/Digraph.h
new file mode 100644
index 0000000..9e1b604
--- /dev/null
+++ b/include/mcld/ADT/GraphLite/Digraph.h
@@ -0,0 +1,85 @@
+//===- Digraph.h ----------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ADT_GRAPHLITE_DIGRAPH_H
+#define MCLD_ADT_GRAPHLITE_DIGRAPH_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/ADT/Uncopyable.h>
+#include <mcld/ADT/GraphLite/GraphBasicTypes.h>
+#include <stdint.h>
+
+namespace mcld {
+namespace graph {
+
+/** \class Digraph
+ * \brief Digraph provides the common interface of all directed graphs.
+ */
+class Digraph : private Uncopyable
+{
+public:
+ typedef DirectedTag direction_tag;
+
+ class Node
+ {
+ friend class Digraph;
+ public:
+ Node() {}
+
+ bool operator==(const Node& pOther) const { return m_ID == pOther.m_ID; }
+ bool operator!=(const Node& pOther) const { return m_ID != pOther.m_ID; }
+
+ protected:
+ intptr_t m_ID;
+ };
+
+ class Arc
+ {
+ friend class Digraph;
+ public:
+ Arc();
+
+ bool operator==(const Node& pOther) const;
+ bool operator!=(const Node& pOther) const;
+
+ Node source() const;
+ Node target() const;
+
+ protected:
+ Arc(Digraph& pParent);
+
+ protected:
+ intptr_t m_ID;
+ Digraph* m_Parent;
+ };
+
+public:
+ Digraph();
+
+ Node addNode();
+
+ Arc addArc(const Node& pSource, const Node& pTarget);
+
+ void erase(const Node& pNode);
+
+ void erase(const Arc& pArc);
+
+ void clear();
+
+ unsigned int numOfNodes() const;
+
+ unsigned int numOfArcs() const;
+
+};
+
+} // namespace of graph
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/ADT/GraphLite/GraphBasicTypes.h b/include/mcld/ADT/GraphLite/GraphBasicTypes.h
new file mode 100644
index 0000000..5862bcb
--- /dev/null
+++ b/include/mcld/ADT/GraphLite/GraphBasicTypes.h
@@ -0,0 +1,29 @@
+//===- GraphBasicTypes.h --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ADT_GRAPHLITE_GRAPHBASICTYPES_H
+#define MCLD_ADT_GRAPHLITE_GRAPHBASICTYPES_H
+
+namespace mcld {
+namespace graph {
+
+/** \class UndirectedTag
+ * \brief Undirected graph category.
+ */
+struct UndirectedTag {};
+
+/** \class DirectedTag
+ * \brief Directed graph category.
+ */
+struct DirectedTag {};
+
+} // namespace of graph
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/ADT/GraphLite/ListDigraph.h b/include/mcld/ADT/GraphLite/ListDigraph.h
new file mode 100644
index 0000000..4ae2c50
--- /dev/null
+++ b/include/mcld/ADT/GraphLite/ListDigraph.h
@@ -0,0 +1,92 @@
+//===- ListDigraph.h ------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ADT_GRAPHLITE_LISTDIGRAPH_H
+#define MCLD_ADT_GRAPHLITE_LISTDIGRAPH_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Support/GCFactory.h>
+
+namespace mcld {
+namespace graph {
+
+/** \class ListDigraph
+ * \brief ListDigraph provides an linked-list inplementation of a graph.
+ *
+ * ListDigraph is designed to get well performance for most algorithms of
+ * graph theory.
+ *
+ * Function | Complexity | Best Complexity
+ * ----------------|------------|--------------------------
+ * Storage | V + E |
+ * Add node | O(1) |
+ * Add arc | O(1) |
+ * Remove node | O(E) | O(#(fan-in) + #(fan-out))
+ * Remove edge | O(1) |
+ * Query adjacency | O(E) | O(#(fan-in) + #(fan-out))
+ *
+ */
+class ListDigraph
+{
+public:
+ struct Node;
+ struct Arc;
+
+ struct Node {
+ public:
+ Node();
+
+ public:
+ Node *prev, *next;
+ Arc *first_in, *first_out;
+ };
+
+ struct Arc {
+ public:
+ Arc();
+
+ public:
+ Node *target, *source;
+ Arc *prev_in, *next_in;
+ Arc *prev_out, *next_out;
+ };
+
+public:
+ ListDigraph();
+
+ Node* addNode();
+
+ Arc* addArc(Node& pU, Node& pV);
+
+ void erase(Node& pNode);
+
+ void erase(Arc& pArc);
+
+ void clear();
+
+ void getHead(Node*& pNode) const { pNode = m_pNodeHead; }
+
+private:
+ typedef GCFactory<Node, 0> NodeList;
+ typedef GCFactory<Arc, 0> ArcList;
+
+private:
+ Node* m_pNodeHead;
+ Node* m_pFreeNodeHead;
+ Arc* m_pFreeArcHead;
+
+ NodeList m_NodeList;
+ ArcList m_ArcList;
+};
+
+} // namespace of graph
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/ADT/HashBase.h b/include/mcld/ADT/HashBase.h
index 896f5b8..f3332a0 100644
--- a/include/mcld/ADT/HashBase.h
+++ b/include/mcld/ADT/HashBase.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_HASH_BASE_H
-#define MCLD_HASH_BASE_H
+#ifndef MCLD_ADT_HASHBASE_H
+#define MCLD_ADT_HASHBASE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/ADT/HashBase.tcc b/include/mcld/ADT/HashBase.tcc
index 165f4ae..50f6ac4 100644
--- a/include/mcld/ADT/HashBase.tcc
+++ b/include/mcld/ADT/HashBase.tcc
@@ -7,8 +7,9 @@
//
//===----------------------------------------------------------------------===//
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
// internal non-member functions
+//===----------------------------------------------------------------------===//
inline static unsigned int compute_bucket_count(unsigned int pNumOfBuckets)
{
static const unsigned int bucket_size[] =
@@ -30,8 +31,9 @@
return (pNumOfBuckets+131101); // rare case. increase constantly
}
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
// template implementation of HashBucket
+//===----------------------------------------------------------------------===//
template<typename DataType>
typename HashBucket<DataType>::entry_type*
HashBucket<DataType>::getEmptyBucket()
@@ -48,8 +50,9 @@
return tombstone;
}
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
// template implementation of HashTableImpl
+//===----------------------------------------------------------------------===//
template<typename HashEntryTy,
typename HashFunctionTy>
HashTableImpl<HashEntryTy, HashFunctionTy>::HashTableImpl()
diff --git a/include/mcld/ADT/HashEntry.h b/include/mcld/ADT/HashEntry.h
index c034783..5c3557f 100644
--- a/include/mcld/ADT/HashEntry.h
+++ b/include/mcld/ADT/HashEntry.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_HASH_ENTRY_H
-#define MCLD_HASH_ENTRY_H
+#ifndef MCLD_ADT_HASHENTRY_H
+#define MCLD_ADT_HASHENTRY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/ADT/HashEntryFactory.h b/include/mcld/ADT/HashEntryFactory.h
index 42aa5e7..91deab4 100644
--- a/include/mcld/ADT/HashEntryFactory.h
+++ b/include/mcld/ADT/HashEntryFactory.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_HASH_ENTRY_FACTORY_H
-#define MCLD_HASH_ENTRY_FACTORY_H
+#ifndef MCLD_ADT_HASHENTRYFACTORY_H
+#define MCLD_ADT_HASHENTRYFACTORY_H
namespace mcld {
diff --git a/include/mcld/ADT/HashIterator.h b/include/mcld/ADT/HashIterator.h
index 078b20a..c25870f 100644
--- a/include/mcld/ADT/HashIterator.h
+++ b/include/mcld/ADT/HashIterator.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_HASH_ITERATOR_H
-#define MCLD_HASH_ITERATOR_H
+#ifndef MCLD_ADT_HASHITERATOR_H
+#define MCLD_ADT_HASHITERATOR_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/ADT/HashTable.h b/include/mcld/ADT/HashTable.h
index 0b6757e..522ab48 100644
--- a/include/mcld/ADT/HashTable.h
+++ b/include/mcld/ADT/HashTable.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_HASH_TABLE_H
-#define MCLD_HASH_TABLE_H
+#ifndef MCLD_ADT_HASHTABLE_H
+#define MCLD_ADT_HASHTABLE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/ADT/SizeTraits.h b/include/mcld/ADT/SizeTraits.h
index dbd5d7b..3baf129 100644
--- a/include/mcld/ADT/SizeTraits.h
+++ b/include/mcld/ADT/SizeTraits.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_SIZE_TRAITS_H
-#define MCLD_SIZE_TRAITS_H
+#ifndef MCLD_ADT_SIZETRAITS_H
+#define MCLD_ADT_SIZETRAITS_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -153,6 +153,36 @@
((pData & 0x00000000000000FFULL) << 56));
}
+template<size_t SIZE>
+typename SizeTraits<SIZE>::Word bswap(typename SizeTraits<SIZE>::Word pData);
+
+template<>
+inline SizeTraits<32>::Word bswap<32>(SizeTraits<32>::Word pData)
+{
+ return bswap32(pData);
+}
+
+template<>
+inline SizeTraits<64>::Word bswap<64>(SizeTraits<64>::Word pData)
+{
+ return bswap64(pData);
+}
+
+template <size_t WIDTH>
+inline uint64_t signExtend(uint64_t pVal)
+{
+ uint64_t mask = (~((uint64_t)0)) >> (64 - WIDTH);
+ uint64_t sign_bit = 1 << (WIDTH - 1);
+
+ return ((pVal & mask) ^ sign_bit) - sign_bit;
+}
+
+template <>
+inline uint64_t signExtend<64>(uint64_t pVal)
+{
+ return pVal;
+}
+
template <size_t SizeOfStr, typename FieldType>
class StringSizerHelper
{
diff --git a/include/mcld/ADT/StringEntry.h b/include/mcld/ADT/StringEntry.h
index e6d1c20..3588c05 100644
--- a/include/mcld/ADT/StringEntry.h
+++ b/include/mcld/ADT/StringEntry.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_STRING_ENTRY_H
-#define MCLD_STRING_ENTRY_H
+#ifndef MCLD_ADT_STRINGENTRY_H
+#define MCLD_ADT_STRINGENTRY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/ADT/StringHash.h b/include/mcld/ADT/StringHash.h
index a9c0025..048f35f 100644
--- a/include/mcld/ADT/StringHash.h
+++ b/include/mcld/ADT/StringHash.h
@@ -6,15 +6,15 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_STRING_HASH_FUNCTION_H
-#define MCLD_STRING_HASH_FUNCTION_H
+#ifndef MCLD_ADT_STRINGHASH_H
+#define MCLD_ADT_STRINGHASH_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <llvm/ADT/StringRef.h>
#include <llvm/Support/DataTypes.h>
-#include <llvm/Support/ErrorHandling.h>
#include <cctype>
+#include <cassert>
#include <functional>
namespace mcld {
@@ -43,7 +43,8 @@
{
uint32_t operator()(const llvm::StringRef& pKey) const
{
- llvm::report_fatal_error("Undefined StringHash function.\n");
+ assert(false && "Undefined StringHash function.\n");
+ return 0;
}
};
diff --git a/include/mcld/ADT/TreeAllocator.h b/include/mcld/ADT/TreeAllocator.h
index 10de761..b2bb39b 100644
--- a/include/mcld/ADT/TreeAllocator.h
+++ b/include/mcld/ADT/TreeAllocator.h
@@ -6,13 +6,13 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_TREE_ALLOCATOR_H
-#define MCLD_TREE_ALLOCATOR_H
+#ifndef MCLD_ADT_TREEALLOCATOR_H
+#define MCLD_ADT_TREEALLOCATOR_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <set>
-#include "mcld/Support/GCFactory.h"
+#include <mcld/Support/GCFactory.h>
namespace mcld {
diff --git a/include/mcld/ADT/TreeBase.h b/include/mcld/ADT/TreeBase.h
index 13eb474..bca375f 100644
--- a/include/mcld/ADT/TreeBase.h
+++ b/include/mcld/ADT/TreeBase.h
@@ -6,9 +6,9 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_TREE_BASE_H
-#define MCLD_TREE_BASE_H
-#include "mcld/ADT/TypeTraits.h"
+#ifndef MCLD_ADT_TREEBASE_H
+#define MCLD_ADT_TREEBASE_H
+#include <mcld/ADT/TypeTraits.h>
#include <cstddef>
#include <cassert>
@@ -28,18 +28,6 @@
{ }
};
-namespace proxy
-{
- template<size_t DIRECT>
- inline void move(NodeBase *&X)
- { assert(0 && "not allowed"); }
-
- template<size_t DIRECT>
- inline void hook(NodeBase *X, const NodeBase *Y)
- { assert(0 && "not allowed"); }
-
-} // namespace of template proxy
-
class TreeIteratorBase
{
public:
@@ -67,9 +55,10 @@
virtual ~TreeIteratorBase(){};
template<size_t DIRECT>
- inline void move() {
- proxy::move<DIRECT>(m_pNode);
- }
+ void move() { assert(0 && "not allowed"); }
+
+ template<size_t DIRECT>
+ void hook(NodeBase* pNode) { assert(0 && "not allowed"); }
bool isRoot() const
{ return (m_pNode->right == m_pNode); }
@@ -87,25 +76,29 @@
{ return this->m_pNode != y.m_pNode; }
};
-namespace proxy
+template<> inline
+void TreeIteratorBase::move<TreeIteratorBase::Leftward>()
{
- template<>
- inline void move<TreeIteratorBase::Leftward>(NodeBase *&X)
- { X = X->left; }
+ this->m_pNode = this->m_pNode->left;
+}
- template<>
- inline void move<TreeIteratorBase::Rightward>(NodeBase *&X)
- { X = X->right; }
+template<> inline
+void TreeIteratorBase::move<TreeIteratorBase::Rightward>()
+{
+ this->m_pNode = this->m_pNode->right;
+}
- template<>
- inline void hook<TreeIteratorBase::Leftward>(NodeBase *X, const NodeBase *Y)
- { X->left = const_cast<NodeBase*>(Y); }
+template<> inline
+void TreeIteratorBase::hook<TreeIteratorBase::Leftward>(NodeBase* pOther)
+{
+ this->m_pNode->left = pOther;
+}
- template<>
- inline void hook<TreeIteratorBase::Rightward>(NodeBase* X, const NodeBase* Y)
- { X->right = const_cast<NodeBase*>(Y); }
-
-} //namespace of template proxy
+template<> inline
+void TreeIteratorBase::hook<TreeIteratorBase::Rightward>(NodeBase* pOther)
+{
+ this->m_pNode->right = pOther;
+}
template<typename DataType>
class Node : public NodeBase
diff --git a/include/mcld/ADT/TypeTraits.h b/include/mcld/ADT/TypeTraits.h
index 90b2224..7f872da 100644
--- a/include/mcld/ADT/TypeTraits.h
+++ b/include/mcld/ADT/TypeTraits.h
@@ -6,16 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_TYPE_TRAITS_H
-#define MCLD_TYPE_TRAITS_H
+#ifndef MCLD_ADT_TYPETRAITS_H
+#define MCLD_ADT_TYPETRAITS_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <cstdlib>
-namespace mcld
-{
+namespace mcld {
+
template<typename DataType>
struct NonConstTraits;
diff --git a/include/mcld/ADT/Uncopyable.h b/include/mcld/ADT/Uncopyable.h
index 7ddfbe3..d899a0a 100644
--- a/include/mcld/ADT/Uncopyable.h
+++ b/include/mcld/ADT/Uncopyable.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_UNCOPYABLE_H
-#define MCLD_UNCOPYABLE_H
+#ifndef MCLD_ADT_UNCOPYABLE_H
+#define MCLD_ADT_UNCOPYABLE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/AttributeOption.h b/include/mcld/AttributeOption.h
index 18d7278..a0130d2 100644
--- a/include/mcld/AttributeOption.h
+++ b/include/mcld/AttributeOption.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ATTRIBUTE_OPTIONS_H
-#define MCLD_ATTRIBUTE_OPTIONS_H
+#ifndef MCLD_ATTRIBUTEOPTION_H
+#define MCLD_ATTRIBUTEOPTION_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/BitcodeOption.h b/include/mcld/BitcodeOption.h
index 4e9a5e1..6d2b9b7 100644
--- a/include/mcld/BitcodeOption.h
+++ b/include/mcld/BitcodeOption.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_BITCODE_OPTIONS_H
-#define MCLD_BITCODE_OPTIONS_H
+#ifndef MCLD_BITCODEOPTION_H
+#define MCLD_BITCODEOPTION_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/CodeGen/MCLinker.h b/include/mcld/CodeGen/MCLinker.h
index 34ddcb7..10423bb 100644
--- a/include/mcld/CodeGen/MCLinker.h
+++ b/include/mcld/CodeGen/MCLinker.h
@@ -28,10 +28,10 @@
namespace mcld {
class Module;
-class MemoryArea;
class IRBuilder;
class LinkerConfig;
class Linker;
+class FileHandle;
/** \class MCLinker
* \brief MCLinker provides a linking pass for standard compilation flow
@@ -54,7 +54,7 @@
// - the standard symbols
MCLinker(LinkerConfig& pConfig,
mcld::Module& pModule,
- MemoryArea& pOutput);
+ FileHandle& pFileHandle);
public:
virtual ~MCLinker();
@@ -71,7 +71,7 @@
protected:
LinkerConfig& m_Config;
mcld::Module& m_Module;
- MemoryArea& m_Output;
+ FileHandle& m_FileHandle;
IRBuilder* m_pBuilder;
Linker* m_pLinker;
diff --git a/include/mcld/Target/TargetMachine.h b/include/mcld/CodeGen/TargetMachine.h
similarity index 66%
rename from include/mcld/Target/TargetMachine.h
rename to include/mcld/CodeGen/TargetMachine.h
index 669e860..6454d87 100644
--- a/include/mcld/Target/TargetMachine.h
+++ b/include/mcld/CodeGen/TargetMachine.h
@@ -6,12 +6,9 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_TARGET_MACHINE_H
-#define MCLD_TARGET_TARGET_MACHINE_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <llvm/Target/TargetMachine.h>
+#ifndef MCLD_CODEGEN_TARGETMACHINE_H
+#define MCLD_CODEGEN_TARGETMACHINE_H
+#include <llvm/Support/CodeGen.h>
#include <string>
namespace llvm {
@@ -19,20 +16,22 @@
class Target;
class TargetData;
class TargetMachine;
+class MCContext;
+class raw_ostream;
+class formatted_raw_ostream;
+namespace legacy {
class PassManagerBase;
-
-} // namespace of llvm
+} // namepsace legacy
+} // namespace llvm
namespace mcld {
class Module;
class Target;
-class MemoryArea;
+class FileHandle;
class LinkerConfig;
class ToolOutputFile;
-using namespace llvm;
-
enum CodeGenFileType {
CGFT_ASMFile,
CGFT_OBJFile,
@@ -52,9 +51,10 @@
public:
/// Adapter of llvm::TargetMachine
///
- MCLDTargetMachine(llvm::TargetMachine &pTM,
- const mcld::Target &pTarget,
- const std::string &pTriple);
+ MCLDTargetMachine(llvm::TargetMachine& pTM,
+ const llvm::Target& pLLMVTarget,
+ const mcld::Target& pMCLDTarget,
+ const std::string& pTriple);
virtual ~MCLDTargetMachine();
@@ -67,48 +67,41 @@
/// appPassesToEmitFile - The target function which we has to modify as
/// upstreaming.
- bool addPassesToEmitFile(PassManagerBase &,
+ bool addPassesToEmitFile(llvm::legacy::PassManagerBase &,
mcld::ToolOutputFile& pOutput,
mcld::CodeGenFileType,
- CodeGenOpt::Level,
+ llvm::CodeGenOpt::Level,
mcld::Module& pModule,
mcld::LinkerConfig& pConfig,
bool DisableVerify = true);
- /// getDataLayout
- const DataLayout *getDataLayout() const { return m_TM.getDataLayout(); }
-
- /// setAsmVerbosityDefault
- static void setAsmVerbosityDefault(bool pAsmVerbose) {
- llvm::TargetMachine::setAsmVerbosityDefault(pAsmVerbose);
- }
-
private:
/// addCommonCodeGenPasses - Add standard LLVM codegen passes used for
/// both emitting to assembly files or machine code output.
- bool addCommonCodeGenPasses(PassManagerBase &,
+ bool addCommonCodeGenPasses(llvm::legacy::PassManagerBase &,
mcld::CodeGenFileType,
- CodeGenOpt::Level,
+ llvm::CodeGenOpt::Level,
bool DisableVerify,
llvm::MCContext *&OutCtx);
- bool addCompilerPasses(PassManagerBase &pPM,
+ bool addCompilerPasses(llvm::legacy::PassManagerBase &pPM,
llvm::formatted_raw_ostream &pOutput,
llvm::MCContext *&OutCtx);
- bool addAssemblerPasses(PassManagerBase &pPM,
+ bool addAssemblerPasses(llvm::legacy::PassManagerBase &pPM,
llvm::raw_ostream &pOutput,
llvm::MCContext *&OutCtx);
- bool addLinkerPasses(PassManagerBase &pPM,
- LinkerConfig& pConfig,
- Module& pModule,
- mcld::MemoryArea& pOutput,
+ bool addLinkerPasses(llvm::legacy::PassManagerBase &pPM,
+ mcld::LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ mcld::FileHandle& pFileHandle,
llvm::MCContext *&OutCtx);
private:
llvm::TargetMachine &m_TM;
- const mcld::Target *m_pTarget;
+ const llvm::Target *m_pLLVMTarget;
+ const mcld::Target *m_pMCLDTarget;
const std::string& m_Triple;
};
diff --git a/include/mcld/Config/Config.h b/include/mcld/Config/Config.h
index 94946df..9e52d54 100644
--- a/include/mcld/Config/Config.h
+++ b/include/mcld/Config/Config.h
@@ -40,5 +40,7 @@
#define MCLD_SYMBOLS_PER_INPUT 128
#define MCLD_RELOCATIONS_PER_INPUT 1024
+#define MCLD_SEGMENTS_PER_OUTPUT 8
+
#endif
diff --git a/include/mcld/Fragment/AlignFragment.h b/include/mcld/Fragment/AlignFragment.h
index 14d0051..1175c07 100644
--- a/include/mcld/Fragment/AlignFragment.h
+++ b/include/mcld/Fragment/AlignFragment.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_ALIGNFRAGMENT_H
-#define MCLD_LD_ALIGNFRAGMENT_H
+#ifndef MCLD_FRAGMENT_ALIGNFRAGMENT_H
+#define MCLD_FRAGMENT_ALIGNFRAGMENT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Fragment/FGNode.h b/include/mcld/Fragment/FGNode.h
deleted file mode 100644
index 0afee0e..0000000
--- a/include/mcld/Fragment/FGNode.h
+++ /dev/null
@@ -1,91 +0,0 @@
-//===- FGNode.h -----------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_FGNODE_H
-#define MCLD_FGNODE_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <llvm/Support/DataTypes.h>
-
-#include <vector>
-
-namespace mcld
-{
-
-class Relocation;
-class ResolveInfo;
-class Fragment;
-
-/** \class FGNode
- * \brief FGNode is a node for FragmentGraph
- */
-class FGNode
-{
-public:
- typedef ResolveInfo* Slot;
- typedef Relocation* Signal;
-
- typedef std::vector<Fragment*> FragmentListType;
- typedef FragmentListType::iterator frag_iterator;
- typedef FragmentListType::const_iterator const_frag_iterator;
-
- typedef std::vector<Slot> SlotListType;
- typedef SlotListType::iterator slot_iterator;
- typedef SlotListType::const_iterator const_slot_iterator;
-
- typedef std::vector<Signal> SignalListType;
- typedef SignalListType::iterator signal_iterator;
- typedef SignalListType::const_iterator const_signal_iterator;
-
-public:
- FGNode();
- explicit FGNode(uint32_t pIndex);
-
- void addFragment(Fragment* pFrag);
- void addSignal(Signal pSignal);
- void addSlot(Slot pSlot);
-
- /// ----- observers ----- ///
- uint32_t getIndex() const
- { return m_Index; }
-
- slot_iterator slot_begin () { return m_Slots.begin(); }
- const_slot_iterator slot_begin () const { return m_Slots.begin(); }
- slot_iterator slot_end () { return m_Slots.end(); }
- const_slot_iterator slot_end () const { return m_Slots.end(); }
-
- signal_iterator signal_begin () { return m_Signals.begin(); }
- const_signal_iterator signal_begin () const { return m_Signals.begin(); }
- signal_iterator signal_end () { return m_Signals.end(); }
- const_signal_iterator signal_end () const { return m_Signals.end(); }
-
- frag_iterator frag_begin () { return m_Fragments.begin(); }
- const_frag_iterator frag_begin () const { return m_Fragments.begin(); }
- frag_iterator frag_end () { return m_Fragments.end(); }
- const_frag_iterator frag_end () const { return m_Fragments.end(); }
-
-private:
- FragmentListType m_Fragments;
-
- /// m_Signals - a list of relocations describes the possible fan-out of this
- /// node
- SignalListType m_Signals;
-
- /// m_Slots - a list of symbols describes the possible fan-in of this node
- SlotListType m_Slots;
-
- /// m_Index - the index in the reachability matrix
- uint32_t m_Index;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Fragment/FillFragment.h b/include/mcld/Fragment/FillFragment.h
index af78237..aa32ec8 100644
--- a/include/mcld/Fragment/FillFragment.h
+++ b/include/mcld/Fragment/FillFragment.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_FILLFRAGMENT_H
-#define MCLD_LD_FILLFRAGMENT_H
+#ifndef MCLD_FRAGMENT_FILLFRAGMENT_H
+#define MCLD_FRAGMENT_FILLFRAGMENT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Fragment/FragmentGraph.h b/include/mcld/Fragment/FragmentGraph.h
deleted file mode 100644
index 96d438f..0000000
--- a/include/mcld/Fragment/FragmentGraph.h
+++ /dev/null
@@ -1,177 +0,0 @@
-//===- FragmentGraph.h ----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_FRAGMENTGRAPH_H
-#define MCLD_FRAGMENTGRAPH_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <vector>
-
-#include <mcld/ADT/HashTable.h>
-#include <mcld/ADT/HashEntry.h>
-#include <mcld/Config/Config.h>
-#include <mcld/Fragment/FGNode.h>
-#include <mcld/Fragment/FGEdge.h>
-#include <mcld/Support/GCFactory.h>
-
-#include <llvm/Support/DataTypes.h>
-
-namespace mcld
-{
-class Module;
-class ResolveInfo;
-class Relocation;
-class LinkerConfig;
-
-/** \class FragmentGraph
- * \brief FragmentGraph describes the references between fragments.
- */
-class FragmentGraph
-{
-public:
- typedef FGNode::Slot Slot;
- typedef FGNode::Signal Signal;
-
- typedef GCFactory<FGNode, MCLD_SECTIONS_PER_INPUT> NodeFactoryType;
- typedef NodeFactoryType::iterator node_iterator;
- typedef NodeFactoryType::const_iterator const_node_iterator;
-
- typedef std::vector<FGEdge> EdgeListType;
- typedef EdgeListType::iterator edge_iterator;
- typedef EdgeListType::const_iterator const_edge_iterator;
-
-
-public:
- FragmentGraph();
- ~FragmentGraph();
-
- /// construct - construct the whole graph from input Fragments, relocations
- /// and symbols
- bool construct(const LinkerConfig& pConfig, Module& pModule);
-
- /// connect - connect two nodes
- bool connect(Signal pSignal, Slot pSlot);
- bool connect(FGNode& pFrom, Slot pSlot);
-
- /// getEdges - given a node, get the list of edges which are the fan-out of
- /// this node
- /// @param pEdges - the edge list which contains the found edges
- /// @return false - the given node
- bool getEdges(FGNode& pNode, EdgeListType& pEdges);
-
- /// ----- observers -----///
- /// getNode - given a fragment, finde the node which the fragment is belong to
- FGNode* getNode(const Fragment& pFrag);
- const FGNode* getNode(const Fragment& pFrag) const;
-
- FGNode* getNode(const ResolveInfo& pSym);
- const FGNode* getNode(const ResolveInfo& pSym) const;
-
-private:
- typedef std::vector<Relocation*> RelocationListType;
- typedef RelocationListType::iterator reloc_iterator;
- typedef RelocationListType::const_iterator const_reloc_iterator;
-
- struct PtrCompare
- {
- bool operator()(const void* X, const void* Y) const
- { return (X==Y); }
- };
-
- struct PtrHash
- {
- size_t operator()(const void* pKey) const
- {
- return (unsigned((uintptr_t)pKey) >> 4) ^
- (unsigned((uintptr_t)pKey) >> 9);
- }
- };
-
- /// HashTable for Fragment* to Node*
- typedef HashEntry<const Fragment*, FGNode*, PtrCompare> FragHashEntryType;
- typedef HashTable<FragHashEntryType,
- PtrHash,
- EntryFactory<FragHashEntryType> > FragHashTableType;
-
- /// HashTable for ResolveInfo* to Node*
- typedef HashEntry<const ResolveInfo*, FGNode*, PtrCompare> SymHashEntryType;
- typedef HashTable<SymHashEntryType,
- PtrHash,
- EntryFactory<SymHashEntryType> > SymHashTableType;
-
- /** \class ReachMatrix
- * \brief ReachMatrix is the reachability matrix which describes the relation
- * of Nodes in FragmentGraph
- */
- class ReachMatrix
- {
- public:
- typedef std::vector<uint32_t> MatrixDataType;
-
- public:
- ReachMatrix(size_t pSize);
- ~ReachMatrix();
- uint32_t& at(uint32_t pX, uint32_t pY);
- uint32_t at(uint32_t pX, uint32_t pY) const;
-
- uint32_t getN() const
- { return m_N; }
-
- void print();
-
- private:
- // m_Data - the contents of the matrix. Here we use a one dimensional array
- // to represent the two dimensional matrix
- MatrixDataType m_Data;
-
- // m_N - this is an m_N x m_N matrix
- size_t m_N;
- };
-
-private:
- FGNode* producePseudoNode();
- FGNode* produceRegularNode();
- void destroyPseudoNode();
- void destroyRegularNode();
-
- void initMatrix();
-
- bool createRegularNodes(Module& pModule);
- bool setNodeSlots(Module& pModule);
- bool createPseudoNodes(Module& pModule);
-
- bool createRegularEdges(Module& pModule);
- bool createPseudoEdges(Module& pModule);
-
-private:
- NodeFactoryType* m_pPseudoNodeFactory;
- NodeFactoryType* m_pRegularNodeFactory;
-
- /// m_pFragNodeMap - HashTable to map the fragment to the node it belongs to
- FragHashTableType* m_pFragNodeMap;
-
- /// m_pSymNodeMap - HashTable to map the ResolveInfo to the node. The node is
- /// the pseudo node which the contains it's fan-out is to the ResolveInfo
- SymHashTableType* m_pSymNodeMap;
-
- ReachMatrix* m_pMatrix;
-
- /// m_NumOfPNodes - number of pseudo nodes
- size_t m_NumOfPNodes;
- /// m_NumOfRNodes - number of regular nodes
- size_t m_NumOfRNodes;
- /// m_NumOfEdges - number of edges
- size_t m_NumOfEdges;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Fragment/FragmentLinker.h b/include/mcld/Fragment/FragmentLinker.h
deleted file mode 100644
index 45ef85d..0000000
--- a/include/mcld/Fragment/FragmentLinker.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//===- FragmentLinker.h ---------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides a number of APIs used by SectLinker.
-// These APIs do the things which a linker should do.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_FRAGMENT_FRAGMENT_LINKER_H
-#define MCLD_FRAGMENT_FRAGMENT_LINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <string>
-
-#include <mcld/LinkerConfig.h>
-#include <mcld/LD/LDFileFormat.h>
-#include <mcld/LD/LDSymbol.h>
-#include <mcld/Fragment/Relocation.h>
-#include <mcld/MC/MCLDInput.h>
-
-namespace mcld {
-
-class Module;
-class TargetLDBackend;
-class LinkerConfig;
-class MemoryArea;
-
-/** \class FragmentLinker
- * \brief FragmentLinker provides a pass to link object files.
- */
-class FragmentLinker
-{
-public:
- FragmentLinker(const LinkerConfig& pConfig,
- Module& pModule,
- TargetLDBackend& pBackend);
-
- ~FragmentLinker();
-
- bool finalizeSymbols();
-
- /// applyRelocations - apply all relocation enties.
- bool applyRelocations();
-
- /// syncRelocationResult - After applying relocation, write back relocation target
- /// data to output file.
- void syncRelocationResult(MemoryArea& pOutput);
-
-private:
- /// normalSyncRelocationResult - sync relocation result when producing shared
- /// objects or executables
- void normalSyncRelocationResult(MemoryArea& pOutput);
-
- /// partialSyncRelocationResult - sync relocation result when doing partial
- /// link
- void partialSyncRelocationResult(MemoryArea& pOutput);
-
- /// writeRelocationResult - helper function of syncRelocationResult, write
- /// relocation target data to output
- void writeRelocationResult(Relocation& pReloc, uint8_t* pOutput);
-
-private:
- const LinkerConfig& m_Config;
- Module& m_Module;
- TargetLDBackend& m_Backend;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Fragment/FragmentRef.h b/include/mcld/Fragment/FragmentRef.h
index 3fce7c9..3bfd804 100644
--- a/include/mcld/Fragment/FragmentRef.h
+++ b/include/mcld/Fragment/FragmentRef.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_FRAGMENT_FRAGMENT_REFERENCE_H
-#define MCLD_FRAGMENT_FRAGMENT_REFERENCE_H
+#ifndef MCLD_FRAGMENT_FRAGMENTREF_H
+#define MCLD_FRAGMENT_FRAGMENTREF_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -78,17 +78,6 @@
Offset getOutputOffset() const;
- // ----- dereference ----- //
- Address deref();
-
- ConstAddress deref() const;
-
- Address operator*()
- { return deref(); }
-
- ConstAddress operator*() const
- { return deref(); }
-
private:
friend FragmentRef& NullFragmentRef();
friend class Chunk<FragmentRef, MCLD_SECTIONS_PER_INPUT>;
diff --git a/include/mcld/Fragment/NullFragment.h b/include/mcld/Fragment/NullFragment.h
index 1c84fae..3440453 100644
--- a/include/mcld/Fragment/NullFragment.h
+++ b/include/mcld/Fragment/NullFragment.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_NULL_FRAGMENT_H
-#define MCLD_LD_NULL_FRAGMENT_H
+#ifndef MCLD_FRAGMENT_NULLFRAGMENT_H
+#define MCLD_FRAGMENT_NULLFRAGMENT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Fragment/RegionFragment.h b/include/mcld/Fragment/RegionFragment.h
index e077264..4f1908a 100644
--- a/include/mcld/Fragment/RegionFragment.h
+++ b/include/mcld/Fragment/RegionFragment.h
@@ -6,30 +6,29 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_REGION_FRAGMENT_H
-#define MCLD_LD_REGION_FRAGMENT_H
+#ifndef MCLD_FRAGMENT_REGIONFRAGMENT_H
+#define MCLD_FRAGMENT_REGIONFRAGMENT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <mcld/Fragment/Fragment.h>
+#include <llvm/ADT/StringRef.h>
namespace mcld {
-class MemoryRegion;
-
/** \class RegionFragment
- * \brief RegionFragment is a kind of Fragment containing mcld::MemoryRegion
+ * \brief RegionFragment is a kind of Fragment containing input memory region
*/
class RegionFragment : public Fragment
{
public:
- RegionFragment(MemoryRegion& pRegion, SectionData* pSD = NULL);
+ RegionFragment(llvm::StringRef pRegion, SectionData* pSD = NULL);
~RegionFragment();
- const MemoryRegion& getRegion() const { return m_Region; }
- MemoryRegion& getRegion() { return m_Region; }
+ const llvm::StringRef getRegion() const { return m_Region; }
+ llvm::StringRef getRegion() { return m_Region; }
static bool classof(const Fragment *F)
{ return F->getKind() == Fragment::Region; }
@@ -40,7 +39,7 @@
size_t size() const;
private:
- MemoryRegion& m_Region;
+ llvm::StringRef m_Region;
};
} // namespace of mcld
diff --git a/include/mcld/Fragment/Relocation.h b/include/mcld/Fragment/Relocation.h
index e8c57e4..3824dd5 100644
--- a/include/mcld/Fragment/Relocation.h
+++ b/include/mcld/Fragment/Relocation.h
@@ -34,7 +34,7 @@
typedef uint64_t Address; // FIXME: use SizeTrait<T>::Address instead
typedef uint64_t DWord; // FIXME: use SizeTrait<T>::Word instead
typedef int64_t SWord; // FIXME: use SizeTrait<T>::SWord instead
- typedef uint8_t Type;
+ typedef uint32_t Type;
typedef uint32_t Size;
private:
diff --git a/include/mcld/Fragment/TargetFragment.h b/include/mcld/Fragment/TargetFragment.h
index 665fcea..76148ea 100644
--- a/include/mcld/Fragment/TargetFragment.h
+++ b/include/mcld/Fragment/TargetFragment.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_TARGET_FRAGMENT_H
-#define MCLD_LD_TARGET_FRAGMENT_H
+#ifndef MCLD_FRAGMENT_TARGETFRAGMENT_H
+#define MCLD_FRAGMENT_TARGETFRAGMENT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/GeneralOptions.h b/include/mcld/GeneralOptions.h
index 77232ac..8348b6f 100644
--- a/include/mcld/GeneralOptions.h
+++ b/include/mcld/GeneralOptions.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_GENERAL_OPTIONS_H
-#define MCLD_GENERAL_OPTIONS_H
+#ifndef MCLD_GENERALOPTIONS_H
+#define MCLD_GENERALOPTIONS_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -15,11 +15,11 @@
#include <vector>
#include <mcld/Support/RealPath.h>
#include <mcld/Support/FileSystem.h>
-#include <mcld/MC/ZOption.h>
namespace mcld {
class Input;
+class ZOption;
/** \class GeneralOptions
* \brief GeneralOptions collects the options that not be one of the
@@ -46,6 +46,10 @@
typedef RpathList::iterator rpath_iterator;
typedef RpathList::const_iterator const_rpath_iterator;
+ typedef std::vector<std::string> ScriptList;
+ typedef ScriptList::iterator script_iterator;
+ typedef ScriptList::const_iterator const_script_iterator;
+
typedef std::vector<std::string> AuxiliaryList;
typedef AuxiliaryList::iterator aux_iterator;
typedef AuxiliaryList::const_iterator const_aux_iterator;
@@ -54,11 +58,6 @@
GeneralOptions();
~GeneralOptions();
- /// default link script
- bool hasDefaultLDScript() const;
- const char* defaultLDScript() const;
- void setDefaultLDScript(const std::string& pFilename);
-
/// trace
void setTrace(bool pEnableTrace = true)
{ m_bTrace = pEnableTrace; }
@@ -84,15 +83,6 @@
bool Bgroup() const
{ return m_Bgroup; }
- bool hasEntry() const
- { return !m_Entry.empty(); }
-
- void setEntry(const std::string& pEntry)
- { m_Entry = pEntry; }
-
- const std::string& entry() const
- { return m_Entry; }
-
void setDyld(const std::string& pDyld)
{ m_Dyld = pDyld; }
@@ -132,10 +122,10 @@
{ return m_bColor; }
void setNoUndefined(bool pEnable = true)
- { m_bNoUndefined = pEnable; }
+ { m_NoUndefined = (pEnable?YES:NO); }
void setMulDefs(bool pEnable = true)
- { m_bMulDefs = pEnable; }
+ { m_MulDefs = (pEnable?YES:NO); }
void setEhFrameHdr(bool pEnable = true)
{ m_bCreateEhFrameHdr = pEnable; }
@@ -146,8 +136,11 @@
bool hasCombReloc() const
{ return m_bCombReloc; }
+ bool hasNoUndefined() const
+ { return (Unknown != m_NoUndefined); }
+
bool isNoUndefined() const
- { return m_bNoUndefined; }
+ { return (YES == m_NoUndefined); }
bool hasStackSet() const
{ return (Unknown != m_ExecStack); }
@@ -165,7 +158,10 @@
{ return m_bLoadFltr; }
bool hasMulDefs() const
- { return m_bMulDefs; }
+ { return (Unknown != m_MulDefs); }
+
+ bool isMulDefs() const
+ { return (YES == m_MulDefs); }
bool hasNoCopyReloc() const
{ return m_bNoCopyReloc; }
@@ -278,6 +274,26 @@
bool printMap() const
{ return m_bPrintMap; }
+ void setWarnMismatch(bool pEnable = true)
+ { m_bWarnMismatch = pEnable; }
+
+ bool warnMismatch() const
+ { return m_bWarnMismatch; }
+
+ // --gc-sections
+ void setGCSections(bool pEnable = true)
+ { m_bGCSections = pEnable; }
+
+ bool GCSections() const
+ { return m_bGCSections; }
+
+ // --ld-generated-unwind-info
+ void setGenUnwindInfo(bool pEnable = true)
+ { m_bGenUnwindInfo = pEnable; }
+
+ bool genUnwindInfo() const
+ { return m_bGenUnwindInfo; }
+
// -G, max GP size option
void setGPSize(int gpsize)
{ m_GPSize = gpsize; }
@@ -299,6 +315,15 @@
const_rpath_iterator rpath_end () const { return m_RpathList.end(); }
rpath_iterator rpath_end () { return m_RpathList.end(); }
+ // ----- link-in script ----- //
+ const ScriptList& getScriptList() const { return m_ScriptList; }
+ ScriptList& getScriptList() { return m_ScriptList; }
+
+ const_script_iterator script_begin() const { return m_ScriptList.begin(); }
+ script_iterator script_begin() { return m_ScriptList.begin(); }
+ const_script_iterator script_end () const { return m_ScriptList.end(); }
+ script_iterator script_end () { return m_ScriptList.end(); }
+
// ----- filter and auxiliary filter ----- //
void setFilter(const std::string& pFilter)
{ m_Filter = pFilter; }
@@ -327,21 +352,20 @@
private:
Input* m_pDefaultBitcode;
std::string m_DefaultLDScript;
- std::string m_Entry;
std::string m_Dyld;
std::string m_SOName;
int8_t m_Verbose; // --verbose[=0,1,2]
uint16_t m_MaxErrorNum; // --error-limit=N
uint16_t m_MaxWarnNum; // --warning-limit=N
status m_ExecStack; // execstack, noexecstack
+ status m_NoUndefined; // defs, --no-undefined
+ status m_MulDefs; // muldefs, --allow-multiple-definition
uint64_t m_CommPageSize; // common-page-size=value
uint64_t m_MaxPageSize; // max-page-size=value
bool m_bCombReloc : 1; // combreloc, nocombreloc
- bool m_bNoUndefined : 1; // defs, --no-undefined
bool m_bInitFirst : 1; // initfirst
bool m_bInterPose : 1; // interpose
bool m_bLoadFltr : 1; // loadfltr
- bool m_bMulDefs : 1; // muldefs
bool m_bNoCopyReloc : 1; // nocopyreloc
bool m_bNoDefaultLib : 1; // nodefaultlib
bool m_bNoDelete : 1; // nodelete
@@ -367,9 +391,13 @@
bool m_bNewDTags: 1; // --enable-new-dtags
bool m_bNoStdlib: 1; // -nostdlib
bool m_bPrintMap: 1; // --print-map
+ bool m_bWarnMismatch: 1; // --no-warn-mismatch
+ bool m_bGCSections: 1; // --gc-sections
+ bool m_bGenUnwindInfo: 1; // --ld-generated-unwind-info
uint32_t m_GPSize; // -G, --gpsize
StripSymbolMode m_StripSymbols;
RpathList m_RpathList;
+ ScriptList m_ScriptList;
unsigned int m_HashStyle;
std::string m_Filter;
AuxiliaryList m_AuxiliaryList;
diff --git a/include/mcld/IRBuilder.h b/include/mcld/IRBuilder.h
index e9f1d13..7cacb36 100644
--- a/include/mcld/IRBuilder.h
+++ b/include/mcld/IRBuilder.h
@@ -14,7 +14,7 @@
#ifndef MCLD_IRBUILDER_H
#define MCLD_IRBUILDER_H
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
#include <mcld/MC/InputBuilder.h>
#include <mcld/LD/LDSection.h>
@@ -29,7 +29,6 @@
#include <mcld/Support/Path.h>
#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/raw_mem_ostream.h>
namespace mcld {
@@ -129,19 +128,6 @@
Input* ReadInput(const std::string& pNameSpec);
/// ReadInput - To read an input file and append it to the input tree.
- ///
- /// This function is like to add an input in the command line.
- ///
- /// LLVM compiler usually emits outputs by llvm::raw_ostream.
- /// mcld::raw_mem_ostream inherits llvm::raw_ostream and is suitable to be
- /// the output of LLVM compier. Users can connect LLVM compiler and MCLinker
- /// by passing mcld::raw_mem_ostream from LLVM compiler to MCLinker.
- ///
- /// @param pMemOStream [in] The input raw_mem_stream
- /// @param the create mcld::Input.
- Input* ReadInput(raw_mem_ostream& pMemOStream);
-
- /// ReadInput - To read an input file and append it to the input tree.
/// Another way to open file manually. Use MCLinker's mcld::FileHandle.
Input* ReadInput(FileHandle& pFileHandle);
@@ -470,6 +456,10 @@
uint32_t pOffset,
Relocation::Address pAddend = 0);
+ /// shouldForceLocal - The helper function for AddSymbol to check if the
+ /// symbols should be force to local symbols
+ bool shouldForceLocal(const ResolveInfo& pInfo, const LinkerConfig& pConfig);
+
private:
LDSymbol* addSymbolFromObject(const std::string& pName,
ResolveInfo::Type pType,
diff --git a/include/mcld/InputTree.h b/include/mcld/InputTree.h
index 0c7e060..0213527 100644
--- a/include/mcld/InputTree.h
+++ b/include/mcld/InputTree.h
@@ -6,15 +6,15 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_MC_INPUT_TREE_H
-#define MCLD_MC_INPUT_TREE_H
+#ifndef MCLD_INPUTTREE_H
+#define MCLD_INPUTTREE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <mcld/ADT/BinTree.h>
#include <mcld/ADT/TypeTraits.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
#include <mcld/Support/Path.h>
#include <string>
@@ -182,16 +182,16 @@
// @param DIRECT the direction of the connecting edge of the parent node.
// @param position the parent node
// @param value the value being pushed.
- template<size_t DIRECT, class Pos>
- BinaryTree& join(Pos position, const Input& value) {
+ template<size_t DIRECT>
+ BinaryTree& join(TreeIteratorBase& pPosition, const Input& value) {
node_type *node = BinaryTreeBase<Input>::createNode();
node->data = const_cast<Input*>(&value);
- if (position.isRoot())
- proxy::hook<TreeIteratorBase::Leftward>(position.m_pNode,
- const_cast<const node_type*>(node));
+
+ if (pPosition.isRoot())
+ pPosition.hook<TreeIteratorBase::Leftward>(node);
else
- proxy::hook<DIRECT>(position.m_pNode,
- const_cast<const node_type*>(node));
+ pPosition.hook<DIRECT>(node);
+
return *this;
}
@@ -200,14 +200,13 @@
// @param position the parent node
// @param the tree being joined.
// @return the joined tree
- template<size_t DIRECT, class Pos>
- BinaryTree& merge(Pos position, BinaryTree& pTree) {
+ template<size_t DIRECT>
+ BinaryTree& merge(TreeIteratorBase& pPosition, BinaryTree& pTree) {
if (this == &pTree)
return *this;
if (!pTree.empty()) {
- proxy::hook<DIRECT>(position.m_pNode,
- const_cast<const NodeBase*>(pTree.m_Root.node.left));
+ pPosition.hook<DIRECT>(pTree.m_Root.node.left);
BinaryTreeBase<Input>::m_Root.summon(
pTree.BinaryTreeBase<Input>::m_Root);
BinaryTreeBase<Input>::m_Root.delegate(pTree.m_Root);
@@ -248,20 +247,20 @@
* connects two nodes of the given iterators togather.
*/
struct Mover {
- virtual ~Mover() {}
- virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const = 0;
+ virtual void connect(TreeIteratorBase& pFrom, NodeBase* pTo) const = 0;
virtual void move(TreeIteratorBase& pNode) const = 0;
+ virtual ~Mover() { }
};
/** \class Succeeder
* \brief class Succeeder moves the iterator afterward.
*/
struct Succeeder : public Mover {
- virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const {
- proxy::hook<Positional>(pFrom.m_pNode, pTo.m_pNode);
+ void connect(TreeIteratorBase& pFrom, NodeBase* pTo) const {
+ pFrom.hook<Positional>(pTo);
}
- virtual void move(TreeIteratorBase& pNode) const {
+ void move(TreeIteratorBase& pNode) const {
pNode.move<Positional>();
}
};
@@ -270,11 +269,11 @@
* \brief class Includer moves the iterator downward.
*/
struct Includer : public Mover {
- virtual void connect(TreeIteratorBase& pFrom, const TreeIteratorBase& pTo) const {
- proxy::hook<Inclusive>(pFrom.m_pNode, pTo.m_pNode);
+ void connect(TreeIteratorBase& pFrom, NodeBase* pTo) const {
+ pFrom.hook<Inclusive>(pTo);
}
- virtual void move(TreeIteratorBase& pNode) const {
+ void move(TreeIteratorBase& pNode) const {
pNode.move<Inclusive>();
}
};
@@ -325,12 +324,12 @@
mcld::InputTree::enterGroup(mcld::TreeIteratorBase pRoot)
{
BinTreeTy::node_type* node = createNode();
+
if (pRoot.isRoot())
- proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
- const_cast<const node_type*>(node));
+ pRoot.hook<TreeIteratorBase::Leftward>(node);
else
- proxy::hook<DIRECT>(pRoot.m_pNode,
- const_cast<const node_type*>(node));
+ pRoot.hook<DIRECT>(node);
+
return *this;
}
@@ -340,12 +339,12 @@
{
BinTreeTy::node_type* node = createNode();
node->data = &pInput;
+
if (pRoot.isRoot())
- proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
- const_cast<const node_type*>(node));
+ pRoot.hook<TreeIteratorBase::Leftward>(node);
else
- proxy::hook<DIRECT>(pRoot.m_pNode,
- const_cast<const node_type*>(node));
+ pRoot.hook<DIRECT>(node);
+
return *this;
}
diff --git a/include/mcld/LD/Archive.h b/include/mcld/LD/Archive.h
index 7dc2205..26de7c3 100644
--- a/include/mcld/LD/Archive.h
+++ b/include/mcld/LD/Archive.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ARCHIVE_H
-#define MCLD_ARCHIVE_H
+#ifndef MCLD_LD_ARCHIVE_H
+#define MCLD_LD_ARCHIVE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -26,9 +26,6 @@
class Input;
class InputFactory;
class InputBuilder;
-class AttributeFactory;
-class ContextFactory;
-class MemoryAreaFactory;
/** \class Archive
* \brief This class define the interfacee to Archive files
@@ -40,6 +37,7 @@
static const char THIN_MAGIC[]; ///< magic of thin archive
static const size_t MAGIC_LEN; ///< length of magic string
static const char SVR4_SYMTAB_NAME[]; ///< SVR4 symtab entry name
+ static const char IRIX6_SYMTAB_NAME[]; ///< Irix6 symtab entry name
static const char STRTAB_NAME[]; ///< Name of string table
static const char PAD[]; ///< inter-file align padding
static const char MEMBER_MAGIC[]; ///< fmag field magic #
@@ -98,7 +96,7 @@
public:
typedef HashTable<ArchiveMemberEntryType,
- hash::StringHash<hash::ELF>,
+ hash::StringHash<hash::DJB>,
EntryFactory<ArchiveMemberEntryType> > ArchiveMemberMapType;
struct Symbol
diff --git a/include/mcld/LD/ArchiveReader.h b/include/mcld/LD/ArchiveReader.h
index 5f24f49..eb6bec5 100644
--- a/include/mcld/LD/ArchiveReader.h
+++ b/include/mcld/LD/ArchiveReader.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ARCHIVE_READER_INTERFACE_H
-#define MCLD_ARCHIVE_READER_INTERFACE_H
+#ifndef MCLD_LD_ARCHIVEREADER_H
+#define MCLD_LD_ARCHIVEREADER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -16,6 +16,7 @@
namespace mcld
{
+class LinkerConfig;
class Archive;
/** \class ArchiveReader
@@ -34,7 +35,7 @@
ArchiveReader();
virtual ~ArchiveReader();
- virtual bool readArchive(Archive& pArchive) = 0;
+ virtual bool readArchive(const LinkerConfig& pConfig, Archive& pArchive) = 0;
};
} // namespace of mcld
diff --git a/include/mcld/LD/BSDArchiveReader.h b/include/mcld/LD/BSDArchiveReader.h
index 7abeecc..fd49966 100644
--- a/include/mcld/LD/BSDArchiveReader.h
+++ b/include/mcld/LD/BSDArchiveReader.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_BSD_ARCHIVE_READER_H
-#define MCLD_BSD_ARCHIVE_READER_H
+#ifndef MCLD_LD_BSDARCHIVEREADER_H
+#define MCLD_LD_BSDARCHIVEREADER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -18,6 +18,7 @@
class Input;
class Archive;
+class LinkerConfig;
/** \class BSDArchiveReader
* \brief BSDArchiveReader reads BSD-variant archive files.
@@ -29,8 +30,8 @@
BSDArchiveReader();
~BSDArchiveReader();
- bool readArchive(Archive& pArchive);
- bool isMyFormat(Input& pInput) const;
+ bool readArchive(const LinkerConfig& pConfig, Archive& pArchive);
+ bool isMyFormat(Input& pInput, bool &pContinue) const;
};
} // namespace of mcld
diff --git a/include/mcld/LD/BinaryReader.h b/include/mcld/LD/BinaryReader.h
index e9c47db..6b61dba 100644
--- a/include/mcld/LD/BinaryReader.h
+++ b/include/mcld/LD/BinaryReader.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_Binary_READER_H
-#define MCLD_Binary_READER_H
+#ifndef MCLD_LD_BINARYREADER_H
+#define MCLD_LD_BINARYREADER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -25,16 +25,11 @@
*/
class BinaryReader : public LDReader
{
-protected:
- BinaryReader()
- { }
-
public:
- virtual ~BinaryReader()
- { }
+ virtual ~BinaryReader() = 0;
- virtual bool isMyFormat(Input& pInput) const
- { return true; }
+ virtual bool isMyFormat(Input& pInput, bool &pContinue) const
+ { pContinue = true; return false; }
virtual bool readBinary(Input& pFile) = 0;
};
diff --git a/include/mcld/LD/BranchIsland.h b/include/mcld/LD/BranchIsland.h
index f340f0a..ca1543f 100644
--- a/include/mcld/LD/BranchIsland.h
+++ b/include/mcld/LD/BranchIsland.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_BRANCH_ISLAND_H
-#define MCLD_LD_BRANCH_ISLAND_H
+#ifndef MCLD_LD_BRANCHISLAND_H
+#define MCLD_LD_BRANCHISLAND_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -125,7 +125,7 @@
size_t operator() (const Key& KEY) const
{
llvm::StringRef sym_name(KEY.symbol()->name());
- hash::StringHash<hash::ELF> str_hasher;
+ hash::StringHash<hash::DJB> str_hasher;
return (size_t((uintptr_t)KEY.prototype())) ^
str_hasher(sym_name) ^
KEY.addend();
diff --git a/include/mcld/LD/BranchIslandFactory.h b/include/mcld/LD/BranchIslandFactory.h
index 755cc31..9431fb3 100644
--- a/include/mcld/LD/BranchIslandFactory.h
+++ b/include/mcld/LD/BranchIslandFactory.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_BRANCH_ISLAND_FACTORY_H
-#define MCLD_LD_BRANCH_ISLAND_FACTORY_H
+#ifndef MCLD_LD_BRANCHISLANDFACTORY_H
+#define MCLD_LD_BRANCHISLANDFACTORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -20,6 +20,7 @@
{
class Fragment;
+class Module;
/** \class BranchIslandFactory
* \brief
@@ -37,6 +38,10 @@
~BranchIslandFactory();
+ /// group - group fragments and create islands when needed
+ /// @param pSectionData - the SectionData holds fragments need to be grouped
+ void group(Module& pModule);
+
/// produce - produce a island for the given fragment
/// @param pFragment - the fragment needs a branch island
BranchIsland* produce(Fragment& pFragment);
diff --git a/include/mcld/LD/DWARFLineInfo.h b/include/mcld/LD/DWARFLineInfo.h
index 004d597..4f19312 100644
--- a/include/mcld/LD/DWARFLineInfo.h
+++ b/include/mcld/LD/DWARFLineInfo.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_DWARF_LINE_INFO_H
-#define MCLD_DWARF_LINE_INFO_H
+#ifndef MCLD_LD_DWARFLINEINFO_H
+#define MCLD_LD_DWARFLINEINFO_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/DiagAttribute.inc b/include/mcld/LD/DiagAttribute.inc
new file mode 100644
index 0000000..453ae65
--- /dev/null
+++ b/include/mcld/LD/DiagAttribute.inc
@@ -0,0 +1,19 @@
+// General
+DIAG(warn_unsupported_attribute_section_format, DiagnosticEngine::Warning, "unsupported format of attribute section in input %0 (version=%1).", "unsupported format of attribute section in input %0 (version=%1).")
+DIAG(warn_unrecognized_vendor_subsection, DiagnosticEngine::Warning, "skip unrecognized private vendor subsection with name '%0' in %1.", "skip unrecognized private vendor subsection with name '%0' in %1.")
+
+// ARM attributes
+DIAG(error_unknown_cpu_arch, DiagnosticEngine::Error, "input %0 has unknown CPU architecture profile.", "input %0 has unknown CPU architecture profile.")
+DIAG(warn_mismatch_cpu_arch_profile, DiagnosticEngine::Warning, "conflicting architecture profiles %0 in %1.", "conflicting architecture profiles %0 in %1.")
+DIAG(error_mismatch_mpextension_use, DiagnosticEngine::Error, "conflicting values from Tag_MPextension_use and Tag_MPextension_use_legacy in %0", "conflicting values from Tag_MPextension_use and Tag_MPextension_use_legacy in %0")
+DIAG(warn_mismatch_enum_size, DiagnosticEngine::Warning, "the size of enumerated data item in input %0 (value=%1) is not compatible with the output (value=%2).", "the size of enumerated data item in input %0 (value=%1) is not compatible with the output (value=%2).")
+DIAG(warn_mismatch_fp16_format, DiagnosticEngine::Warning, "conflicting 16-bit FP number format in %0", "conflicting 16-bit FP number format in %0")
+DIAG(warn_unrecognized_virtualization_use, DiagnosticEngine::Warning, "value of Tag_Virtualization_use cannot be recognized in %0 (value=%1).", "value of Tag_Virtualization_use cannot be recognized in %0 (value=%1).")
+DIAG(warn_mismatch_abi_wmmx_args, DiagnosticEngine::Warning, "%0 uses different way to pass WMMX parameters and results.", "%0 uses different way to pass WMMX parameters and results.")
+DIAG(warn_mismatch_pcs_config, DiagnosticEngine::Warning, "conflicting procedure call standard config in input %0.", "conflicting procedure call standard config in input %0.")
+DIAG(warn_mismatch_r9_use, DiagnosticEngine::Warning, "conflicting way to use R9 in input %0.", "conflicting way to use R9 in input %0.")
+DIAG(warn_conflict_rw_data_and_r9, DiagnosticEngine::Warning, "RW static data addressing (SB-relative) conflicts the use of R9 (Tag_ABI_PCS_R9_use) in input %0.", "RW static data addressing (SB-relative) conflicts the use of R9 (Tag_ABI_PCS_R9_use) in input %0.")
+DIAG(warn_mismatch_wchar_size, DiagnosticEngine::Warning, "incompatible size of wchar_t in input %0 (value=%1) with the output (value=%2).", "incompatible size of wchar_t in input %0 (value=%1) with the output (value=%2).")
+DIAG(warn_unknown_mandatory_attribute, DiagnosticEngine::Warning, "unknown mandatory attribute with tag %0 was ignored in %1.", "unknown mandatory attribute with tag %0 was ignored in %1.")
+DIAG(warn_unknown_attribute, DiagnosticEngine::Warning, "unknown attribute with tag %0 was ignored in %1.", "unknown attribute with tag %0 was ignored in %1.")
+DIAG(warn_mismatch_vfp_args, DiagnosticEngine::Warning, "%0 uses different way to pass the floating point parameter and results.", "%0 uses different way to pass the floating point parameter and results.")
diff --git a/include/mcld/LD/DiagCommonKinds.inc b/include/mcld/LD/DiagCommonKinds.inc
index e7d6328..539eafb 100644
--- a/include/mcld/LD/DiagCommonKinds.inc
+++ b/include/mcld/LD/DiagCommonKinds.inc
@@ -3,7 +3,7 @@
DIAG(warn_cannot_open_search_dir, DiagnosticEngine::Warning, "can not open search directory `-L%0'", "can not open search directory `-L%0'")
DIAG(err_no_inputs, DiagnosticEngine::Error, "no inputs", "no inputs")
DIAG(err_empty_input, DiagnosticEngine::Error, "Empty input file `%0' : %1", "Empty input file `%0' : %1")
-DIAG(err_unrecognized_input_file, DiagnosticEngine::Fatal, "cannot recognize the format of file `%0'.\n object format or given target machine (%1) is wrong.","cannot recognize the format of file `%0'.\n object format or given target machine (%1) is wrong.")
+DIAG(warn_unrecognized_input_file, DiagnosticEngine::Warning, "cannot recognize the format of file `%0'.\n object format or given target machine (%1) is incompatible.","cannot recognize the format of file `%0'.\n object format or given target machine (%1) is incompatible.")
DIAG(err_cannot_find_namespec, DiagnosticEngine::Fatal, "cannot recognize namespec -l%0", "cannot recognize namespec -l%0")
DIAG(err_cannot_identify_option, DiagnosticEngine::Fatal, "unknown command line argument `%0' at %1", "unknown command line argument `%0' at %1")
DIAG(err_mixed_shared_static_objects, DiagnosticEngine::Error, "cannot link shared objects with -static option.\nShared object `%0': %1", "cannot link shared objects with -static option.\nShared object `%0': %1")
@@ -40,7 +40,7 @@
DIAG(fatal_cannot_init_target, DiagnosticEngine::Fatal, "Cannot initialize mcld::Target for given triple '%0'.\n(Detail: %1)", "Cannot initialize mcld::Target for given triple '%0'.\n(Detail: %1)")
DIAG(fatal_cannot_init_lineinfo, DiagnosticEngine::Fatal, "Cannot initialize mcld::DiagnosticLineInfo for given triple '%0'", "Cannot initialize mcld::DiagnosticLineInfo for given triple '%0'")
DIAG(fatal_cannot_init_backend, DiagnosticEngine::Fatal, "Cannot initialize mcld::TargetLDBackend for given triple '%0'.", "Cannot initialize mcld::TargetLDBackend for given triple '%0'.")
-DIAG(fatal_forbid_nest_group, DiagnosticEngine::Fatal, "May not nest groups", "May not nest groups")
+DIAG(fatal_forbid_nest_group, DiagnosticEngine::Fatal, "not matched --start-group and --end-group", "not matched --start-group and --end-group")
DIAG(fatal_unwritable_output, DiagnosticEngine::Fatal, "unable to write output file %0", "unable to write output file %0")
DIAG(warn_unsupported_option, DiagnosticEngine::Warning, "Option `%0' is not implemented yet!", "Option `%0' is not implemented yet!")
DIAG(warn_shared_textrel, DiagnosticEngine::Warning, "Add DT_TEXTREL in a shared object!", "Add DT_TEXTREL in a shared object.")
@@ -48,3 +48,6 @@
DIAG(err_nmagic_not_static, DiagnosticEngine::Error, "cannot mix -nmagic option with -shared", "cannot mix -nmagic option with -shared")
DIAG(err_omagic_not_static, DiagnosticEngine::Error, "cannot mix -omagic option with -shared", "cannot mix -omagic option with -shared")
DIAG(err_invalid_emulation, DiagnosticEngine::Error, "Invalid target emulation: `%0'.", "Invalid target emulation: `%0'.")
+DIAG(err_cannot_find_scriptfile, DiagnosticEngine::Fatal, "cannot open %0 file %1", "cannot open %0 file %1")
+DIAG(err_unsupported_archive, DiagnosticEngine::Error, "Unsupported archive type.", "Unsupported archive type.")
+DIAG(unexpected_frag_type, DiagnosticEngine::Unreachable, "Unexpected fragment type `%0' when constructing FG", "Unexpected fragment type `%0' when constructing FG")
diff --git a/include/mcld/LD/DiagLDScript.inc b/include/mcld/LD/DiagLDScript.inc
new file mode 100644
index 0000000..c752773
--- /dev/null
+++ b/include/mcld/LD/DiagLDScript.inc
@@ -0,0 +1,3 @@
+DIAG(err_unterminated_comment, DiagnosticEngine::Error, "%0:%1:%2: error: unterminated comment\n", "%0:%1:%2: error: unterminated comment\n")
+DIAG(err_syntax_error, DiagnosticEngine::Error, "%0:%1:%2: error: %3\n", "%0:%1:%2: error: %3\n")
+DIAG(err_assert_failed, DiagnosticEngine::Error,"Assertion failed: %0\n", "Assertion failed: %0\n")
diff --git a/include/mcld/LD/DiagRelocations.inc b/include/mcld/LD/DiagRelocations.inc
index 7ada05f..bacae6e 100644
--- a/include/mcld/LD/DiagRelocations.inc
+++ b/include/mcld/LD/DiagRelocations.inc
@@ -1,6 +1,7 @@
DIAG(reloc_factory_has_not_config, DiagnosticEngine::Fatal, "Please call mcld::Linker::config before creating relocations", "Please call mcld::Linker::config before creating relocations")
DIAG(unsupported_bitclass, DiagnosticEngine::Fatal, "Only supports 32 and 64 bits targets. (Target: %0, bitclass:%1)", "Only supports 32 and 64 bits targets. (Target: %0, bitclass:%1)")
-DIAG(undefined_reference, DiagnosticEngine::Fatal, "undefined reference to `%0'", "In %1:%2, variable %0 must be defined")
+DIAG(undefined_reference, DiagnosticEngine::Fatal, "%1(%2+%3): undefined reference to `%0'", "%1(%2+%3): undefined reference to `%0'")
+DIAG(undefined_reference_text, DiagnosticEngine::Fatal, "%1:%2:function %3: undefined reference to `%0'", "%1:%2: undefined reference to `%0'")
DIAG(non_pic_relocation, DiagnosticEngine::Error, "attempt to generate unsupported relocation type `%0' for symbol `%1', recompile with -fPIC", "attempt to generate unsupported relocation type `%0' for symbol `%1, recompile with -fPIC")
DIAG(base_relocation, DiagnosticEngine::Fatal, "relocation type `%0' is not supported for symbol `%1'\nPlease report to %2", "relocation type `%0' is not supported for symbol `%1'\nPlease report to %2")
DIAG(dynamic_relocation, DiagnosticEngine::Fatal, "unexpected relocation type `%0' in object file", "unexpected relocation type `%0' in object file")
@@ -11,3 +12,4 @@
DIAG(result_badreloc, DiagnosticEngine::Error, "applying relocation `%0' encounters unexpected opcode on symbol `%1'","applying relocation `%0' encounters unexpected opcode on symbol `%1'")
DIAG(invalid_tls, DiagnosticEngine::Error, "TLS relocation against invalid symbol `%0' in section `%1'", "TLS relocation against invalid symbol `%0' in section `%1'")
DIAG(unknown_reloc_section_type, DiagnosticEngine::Unreachable, "unknown relocation section type: `%0' in section `%1'", "unknown relocation section type: `%0' in section `%1'")
+DIAG(unsupport_cond_branch_reloc, DiagnosticEngine::Error, "applying relocation `%0', conditional branch to PLT in THUMB-2 not supported yet", "applying relocation `%0', conditional branch to PLT in THUMB-2 not supported yet")
diff --git a/include/mcld/LD/DiagSymbolResolutions.inc b/include/mcld/LD/DiagSymbolResolutions.inc
index 786eb4b..04113dc 100644
--- a/include/mcld/LD/DiagSymbolResolutions.inc
+++ b/include/mcld/LD/DiagSymbolResolutions.inc
@@ -8,3 +8,4 @@
DIAG(indirect_refer_to_inexist, DiagnosticEngine::Fatal, "indirect symbol %0 points to a undefined symbol", "variable %0 is undefined")
DIAG(multiple_definitions, DiagnosticEngine::Error, "multiple definition of symbol `%0'", "you define variable %0 twice")
DIAG(undefined_situation, DiagnosticEngine::Unreachable, "reach undefined situation, action: %0, old(%1) -> new(%2)", "reach undefined situation, action: %0, old(%1) -> new(%2)")
+DIAG(multiple_absolute_definitions, DiagnosticEngine::Error, "inconsistent definitions of absolute symbol `%0': old(%1) -> new(%2)", "you defined an absolute symbol with different values")
diff --git a/include/mcld/LD/Diagnostic.h b/include/mcld/LD/Diagnostic.h
index 2e4db11..1982ef0 100644
--- a/include/mcld/LD/Diagnostic.h
+++ b/include/mcld/LD/Diagnostic.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_DIAGNOSTIC_H
-#define MCLD_DIAGNOSTIC_H
+#ifndef MCLD_LD_DIAGNOSTIC_H
+#define MCLD_LD_DIAGNOSTIC_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/DiagnosticEngine.h b/include/mcld/LD/DiagnosticEngine.h
index 1c825a2..b003955 100644
--- a/include/mcld/LD/DiagnosticEngine.h
+++ b/include/mcld/LD/DiagnosticEngine.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_DIAGNOSTIC_ENGINE_H
-#define MCLD_DIAGNOSTIC_ENGINE_H
+#ifndef MCLD_LD_DIAGNOSTICENGINE_H
+#define MCLD_LD_DIAGNOSTICENGINE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/DiagnosticInfos.h b/include/mcld/LD/DiagnosticInfos.h
index cb9bdbd..16ebbab 100644
--- a/include/mcld/LD/DiagnosticInfos.h
+++ b/include/mcld/LD/DiagnosticInfos.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_DIAGNOSTIC_INFORMATION_H
-#define MCLD_DIAGNOSTIC_INFORMATION_H
+#ifndef MCLD_LD_DIAGNOSTICINFORMATION_H
+#define MCLD_LD_DIAGNOSTICINFORMATION_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -18,12 +18,14 @@
namespace diag {
enum ID {
#define DIAG(ENUM, CLASS, ADDRMSG, LINEMSG) ENUM,
+#include "mcld/LD/DiagAttribute.inc"
#include "mcld/LD/DiagCommonKinds.inc"
#include "mcld/LD/DiagReaders.inc"
#include "mcld/LD/DiagSymbolResolutions.inc"
#include "mcld/LD/DiagRelocations.inc"
#include "mcld/LD/DiagLayouts.inc"
#include "mcld/LD/DiagGOTPLT.inc"
+#include "mcld/LD/DiagLDScript.inc"
#undef DIAG
NUM_OF_BUILDIN_DIAGNOSTIC_INFO
};
diff --git a/include/mcld/LD/DiagnosticLineInfo.h b/include/mcld/LD/DiagnosticLineInfo.h
index 30f0546..db35287 100644
--- a/include/mcld/LD/DiagnosticLineInfo.h
+++ b/include/mcld/LD/DiagnosticLineInfo.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_DIAGNOSTICLINEINFO_H
-#define MCLD_DIAGNOSTICLINEINFO_H
+#ifndef MCLD_LD_DIAGNOSTICLINEINFO_H
+#define MCLD_LD_DIAGNOSTICLINEINFO_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/DiagnosticPrinter.h b/include/mcld/LD/DiagnosticPrinter.h
index b3617a7..7cf5c8e 100644
--- a/include/mcld/LD/DiagnosticPrinter.h
+++ b/include/mcld/LD/DiagnosticPrinter.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_DIAGNOSTIC_PRINTER_H
-#define MCLD_DIAGNOSTIC_PRINTER_H
+#ifndef MCLD_LD_DIAGNOSTICPRINTER_H
+#define MCLD_LD_DIAGNOSTICPRINTER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/DynObjFileFormat.h b/include/mcld/LD/DynObjFileFormat.h
index 7b1626d..e0972c3 100644
--- a/include/mcld/LD/DynObjFileFormat.h
+++ b/include/mcld/LD/DynObjFileFormat.h
@@ -1,4 +1,4 @@
-//===- header.h -----------------------------------------------------------===//
+//===- DynObjFileFormat.h -------------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef DYNOBJFORMAT_H
-#define DYNOBJFORMAT_H
+#ifndef MCLD_LD_DYNOBJFILEFORMAT_H
+#define MCLD_LD_DYNOBJFILEFORMAT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/DynObjReader.h b/include/mcld/LD/DynObjReader.h
index ddc9500..8a7a6be 100644
--- a/include/mcld/LD/DynObjReader.h
+++ b/include/mcld/LD/DynObjReader.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_DYNAMIC_SHARED_OBJECT_READER_H
-#define MCLD_DYNAMIC_SHARED_OBJECT_READER_H
+#ifndef MCLD_LD_DYNOBJREADER_H
+#define MCLD_LD_DYNOBJREADER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/ELFBinaryReader.h b/include/mcld/LD/ELFBinaryReader.h
index fc3a067..9da4535 100644
--- a/include/mcld/LD/ELFBinaryReader.h
+++ b/include/mcld/LD/ELFBinaryReader.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_Binary_READER_H
-#define MCLD_ELF_Binary_READER_H
+#ifndef MCLD_LD_ELFBINARYREADER_H
+#define MCLD_LD_ELFBINARYREADER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -19,7 +19,6 @@
class Module;
class Input;
class IRBuilder;
-class GNULDBackend;
class LinkerConfig;
/** \lclass ELFBinaryReader
@@ -28,16 +27,15 @@
class ELFBinaryReader : public BinaryReader
{
public:
- ELFBinaryReader(GNULDBackend& pBackend,
- IRBuilder& pBuilder,
- const LinkerConfig& pConfig);
+ ELFBinaryReader(IRBuilder& pBuilder, const LinkerConfig& pConfig);
~ELFBinaryReader();
- virtual bool readBinary(Input& pInput);
+ bool isMyFormat(Input& pInput, bool &pContinue) const;
+
+ bool readBinary(Input& pInput);
private:
- GNULDBackend& m_Backend;
IRBuilder& m_Builder;
const LinkerConfig& m_Config;
};
diff --git a/include/mcld/LD/ELFDynObjFileFormat.h b/include/mcld/LD/ELFDynObjFileFormat.h
index 2ee97a6..dd9cbb9 100644
--- a/include/mcld/LD/ELFDynObjFileFormat.h
+++ b/include/mcld/LD/ELFDynObjFileFormat.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_DYNAMIC_OBJECT_FILE_FROMAT_H
-#define MCLD_ELF_DYNAMIC_OBJECT_FILE_FROMAT_H
+#ifndef MCLD_LD_ELFDYNOBJFILEFROMAT_H
+#define MCLD_LD_ELFDYNOBJFILEFROMAT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/ELFDynObjReader.h b/include/mcld/LD/ELFDynObjReader.h
index f6d2067..23b96ad 100644
--- a/include/mcld/LD/ELFDynObjReader.h
+++ b/include/mcld/LD/ELFDynObjReader.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_DYNAMIC_SHARED_OBJECT_READER_H
-#define MCLD_ELF_DYNAMIC_SHARED_OBJECT_READER_H
+#ifndef MCLD_LD_ELFDYNOBJREADER_H
+#define MCLD_LD_ELFDYNOBJREADER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -35,7 +35,7 @@
~ELFDynObjReader();
// ----- observers ----- //
- bool isMyFormat(Input &pFile) const;
+ bool isMyFormat(Input &pFile, bool &pContinue) const;
// ----- readers ----- //
bool readHeader(Input& pFile);
diff --git a/include/mcld/LD/ELFObjectReader.h b/include/mcld/LD/ELFObjectReader.h
index 27e4489..a124676 100644
--- a/include/mcld/LD/ELFObjectReader.h
+++ b/include/mcld/LD/ELFObjectReader.h
@@ -46,7 +46,7 @@
~ELFObjectReader();
// ----- observers ----- //
- bool isMyFormat(Input &pFile) const;
+ bool isMyFormat(Input &pFile, bool &pContinue) const;
// ----- readers ----- //
bool readHeader(Input& pFile);
diff --git a/include/mcld/LD/ELFObjectWriter.h b/include/mcld/LD/ELFObjectWriter.h
index 12a5842..9caa76a 100644
--- a/include/mcld/LD/ELFObjectWriter.h
+++ b/include/mcld/LD/ELFObjectWriter.h
@@ -6,18 +6,20 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_OBJECT_WRITER_H
-#define MCLD_ELF_OBJECT_WRITER_H
+#ifndef MCLD_LD_ELFOBJWRITER_H
+#define MCLD_LD_ELFOBJWRITER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <mcld/LD/ObjectWriter.h>
#include <cassert>
+#include <mcld/Support/FileOutputBuffer.h>
#include <llvm/Support/system_error.h>
namespace mcld {
+class EhFrame;
class Module;
class LinkerConfig;
class GNULDBackend;
@@ -27,8 +29,6 @@
class SectionData;
class RelocData;
class Output;
-class MemoryRegion;
-class MemoryArea;
/** \class ELFObjectWriter
* \brief ELFObjectWriter writes the target-independent parts of object files.
@@ -42,10 +42,13 @@
~ELFObjectWriter();
- llvm::error_code writeObject(Module& pModule, MemoryArea& pOutput);
+ llvm::error_code writeObject(Module& pModule, FileOutputBuffer& pOutput);
+
+ size_t getOutputSize(const Module& pModule) const;
private:
- void writeSection(MemoryArea& pOutput, LDSection *section);
+ void writeSection(Module& pModule,
+ FileOutputBuffer& pOutput, LDSection *section);
GNULDBackend& target() { return m_Backend; }
@@ -55,7 +58,7 @@
template<size_t SIZE>
void writeELFHeader(const LinkerConfig& pConfig,
const Module& pModule,
- MemoryArea& pOutput) const;
+ FileOutputBuffer& pOutput) const;
uint64_t getEntryPoint(const LinkerConfig& pConfig,
const Module& pModule) const;
@@ -64,19 +67,21 @@
template<size_t SIZE>
void emitSectionHeader(const Module& pModule,
const LinkerConfig& pConfig,
- MemoryArea& pOutput) const;
+ FileOutputBuffer& pOutput) const;
// emitProgramHeader - emit ElfXX_Phdr
template<size_t SIZE>
- void emitProgramHeader(MemoryArea& pOutput) const;
+ void emitProgramHeader(FileOutputBuffer& pOutput) const;
// emitShStrTab - emit .shstrtab
void emitShStrTab(const LDSection& pShStrTab,
const Module& pModule,
- MemoryArea& pOutput);
+ FileOutputBuffer& pOutput);
- void emitSectionData(const LDSection& pSection,
- MemoryRegion& pRegion) const;
+ void emitSectionData(const LDSection& pSection, MemoryRegion& pRegion) const;
+
+ void emitEhFrame(Module& pModule,
+ EhFrame& pFrame, MemoryRegion& pRegion) const;
void emitRelocation(const LinkerConfig& pConfig,
const LDSection& pSection,
diff --git a/include/mcld/LD/ELFReader.h b/include/mcld/LD/ELFReader.h
index 9df21d3..6750ebd 100644
--- a/include/mcld/LD/ELFReader.h
+++ b/include/mcld/LD/ELFReader.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_READER_H
-#define MCLD_ELF_READER_H
+#ifndef MCLD_LD_ELFREADER_H
+#define MCLD_LD_ELFREADER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -20,8 +20,6 @@
#include <mcld/LD/ResolveInfo.h>
#include <mcld/LD/LDSymbol.h>
#include <mcld/Target/GNULDBackend.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/MemoryArea.h>
namespace mcld {
@@ -60,19 +58,19 @@
{ return sizeof(ELFHeader); }
/// isELF - is this a ELF file
- bool isELF(void* pELFHeader) const;
+ bool isELF(const void* pELFHeader) const;
/// isMyEndian - is this ELF file in the same endian to me?
- bool isMyEndian(void* pELFHeader) const;
+ bool isMyEndian(const void* pELFHeader) const;
/// isMyMachine - is this ELF file generated for the same machine.
- bool isMyMachine(void* pELFHeader) const;
+ bool isMyMachine(const void* pELFHeader) const;
/// fileType - the file type of this file
- Input::Type fileType(void* pELFHeader) const;
+ Input::Type fileType(const void* pELFHeader) const;
/// readSectionHeaders - read ELF section header table and create LDSections
- bool readSectionHeaders(Input& pInput, void* pELFHeader) const;
+ bool readSectionHeaders(Input& pInput, const void* pELFHeader) const;
/// readRegularSection - read a regular section and create fragments.
bool readRegularSection(Input& pInput, SectionData& pSD) const;
@@ -80,24 +78,24 @@
/// readSymbols - read ELF symbols and create LDSymbol
bool readSymbols(Input& pInput,
IRBuilder& pBuilder,
- const MemoryRegion& pRegion,
+ llvm::StringRef pRegion,
const char* StrTab) const;
/// readSignature - read a symbol from the given Input and index in symtab
/// This is used to get the signature of a group section.
ResolveInfo* readSignature(Input& pInput,
- LDSection& pSymTab,
- uint32_t pSymIdx) const;
+ LDSection& pSymTab,
+ uint32_t pSymIdx) const;
/// readRela - read ELF rela and create Relocation
bool readRela(Input& pInput,
LDSection& pSection,
- const MemoryRegion& pRegion) const;
+ llvm::StringRef pRegion) const;
/// readRel - read ELF rel and create Relocation
bool readRel(Input& pInput,
LDSection& pSection,
- const MemoryRegion& pRegion) const;
+ llvm::StringRef pRegion) const;
/// readDynamic - read ELF .dynamic in input dynobj
bool readDynamic(Input& pInput) const;
@@ -150,19 +148,19 @@
{ return sizeof(ELFHeader); }
/// isELF - is this a ELF file
- bool isELF(void* pELFHeader) const;
+ bool isELF(const void* pELFHeader) const;
/// isMyEndian - is this ELF file in the same endian to me?
- bool isMyEndian(void* pELFHeader) const;
+ bool isMyEndian(const void* pELFHeader) const;
/// isMyMachine - is this ELF file generated for the same machine.
- bool isMyMachine(void* pELFHeader) const;
+ bool isMyMachine(const void* pELFHeader) const;
/// fileType - the file type of this file
- Input::Type fileType(void* pELFHeader) const;
+ Input::Type fileType(const void* pELFHeader) const;
/// readSectionHeaders - read ELF section header table and create LDSections
- bool readSectionHeaders(Input& pInput, void* pELFHeader) const;
+ bool readSectionHeaders(Input& pInput, const void* pELFHeader) const;
/// readRegularSection - read a regular section and create fragments.
bool readRegularSection(Input& pInput, SectionData& pSD) const;
@@ -170,24 +168,24 @@
/// readSymbols - read ELF symbols and create LDSymbol
bool readSymbols(Input& pInput,
IRBuilder& pBuilder,
- const MemoryRegion& pRegion,
+ llvm::StringRef pRegion,
const char* StrTab) const;
/// readSignature - read a symbol from the given Input and index in symtab
/// This is used to get the signature of a group section.
ResolveInfo* readSignature(Input& pInput,
- LDSection& pSymTab,
- uint32_t pSymIdx) const;
+ LDSection& pSymTab,
+ uint32_t pSymIdx) const;
/// readRela - read ELF rela and create Relocation
bool readRela(Input& pInput,
LDSection& pSection,
- const MemoryRegion& pRegion) const;
+ llvm::StringRef pRegion) const;
/// readRel - read ELF rel and create Relocation
bool readRel(Input& pInput,
LDSection& pSection,
- const MemoryRegion& pRegion) const;
+ llvm::StringRef pRegion) const;
/// readDynamic - read ELF .dynamic in input dynobj
bool readDynamic(Input& pInput) const;
diff --git a/include/mcld/LD/ELFReaderIf.h b/include/mcld/LD/ELFReaderIf.h
index 245b542..0ce5992 100644
--- a/include/mcld/LD/ELFReaderIf.h
+++ b/include/mcld/LD/ELFReaderIf.h
@@ -1,4 +1,4 @@
-//===- ELFReader.h --------------------------------------------------------===//
+//===- ELFReaderIf.h ------------------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_READER_INTERFACE_H
-#define MCLD_ELF_READER_INTERFACE_H
+#ifndef MCLD_LD_ELFREADERIF_H
+#define MCLD_LD_ELFREADERIF_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -46,16 +46,16 @@
virtual size_t getELFHeaderSize() const = 0;
/// isELF - is this a ELF file
- virtual bool isELF(void* pELFHeader) const = 0;
+ virtual bool isELF(const void* pELFHeader) const = 0;
/// isMyEndian - is this ELF file in the same endian to me?
- virtual bool isMyEndian(void* pELFHeader) const = 0;
+ virtual bool isMyEndian(const void* pELFHeader) const = 0;
/// isMyMachine - is this ELF file generated for the same machine.
- virtual bool isMyMachine(void* pELFHeader) const = 0;
+ virtual bool isMyMachine(const void* pELFHeader) const = 0;
/// fileType - the file type of this file
- virtual Input::Type fileType(void* pELFHeader) const = 0;
+ virtual Input::Type fileType(const void* pELFHeader) const = 0;
/// target - the target backend
const GNULDBackend& target() const { return m_Backend; }
@@ -63,7 +63,8 @@
/// readSectionHeaders - read ELF section header table and create LDSections
- virtual bool readSectionHeaders(Input& pInput, void* pELFHeader) const = 0;
+ virtual bool readSectionHeaders(Input& pInput,
+ const void* pELFHeader) const = 0;
/// readRegularSection - read a regular section and create fragments.
virtual bool readRegularSection(Input& pInput, SectionData& pSD) const = 0;
@@ -71,7 +72,7 @@
/// readSymbols - read ELF symbols and create LDSymbol
virtual bool readSymbols(Input& pInput,
IRBuilder& pBuilder,
- const MemoryRegion& pRegion,
+ llvm::StringRef pRegion,
const char* StrTab) const = 0;
/// readSignature - read a symbol from the given Input and index in symtab
@@ -83,12 +84,12 @@
/// readRela - read ELF rela and create Relocation
virtual bool readRela(Input& pInput,
LDSection& pSection,
- const MemoryRegion& pRegion) const = 0;
+ llvm::StringRef pRegion) const = 0;
/// readRel - read ELF rel and create Relocation
virtual bool readRel(Input& pInput,
LDSection& pSection,
- const MemoryRegion& pRegion) const = 0;
+ llvm::StringRef pRegion) const = 0;
/// readDynamic - read ELF .dynamic in input dynobj
virtual bool readDynamic(Input& pInput) const = 0;
diff --git a/include/mcld/LD/ELFSegment.h b/include/mcld/LD/ELFSegment.h
index d7f769e..5079b54 100644
--- a/include/mcld/LD/ELFSegment.h
+++ b/include/mcld/LD/ELFSegment.h
@@ -6,45 +6,52 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_SEGMENT_H
-#define MCLD_ELF_SEGMENT_H
+#ifndef MCLD_LD_ELFSEGMENT_H
+#define MCLD_LD_ELFSEGMENT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
#include <llvm/Support/ELF.h>
#include <llvm/Support/DataTypes.h>
-#include <mcld/LD/LDSection.h>
-#include <cassert>
#include <vector>
namespace mcld
{
+class LDSection;
+
/** \class ELFSegment
* \brief decribe the program header for ELF executable or shared object
*/
class ELFSegment
{
public:
- typedef std::vector<LDSection*>::iterator sect_iterator;
- typedef std::vector<LDSection*>::const_iterator const_sect_iterator;
+ typedef std::vector<LDSection*> SectionList;
+ typedef SectionList::iterator iterator;
+ typedef SectionList::const_iterator const_iterator;
+ typedef SectionList::reverse_iterator reverse_iterator;
+ typedef SectionList::const_reverse_iterator const_reverse_iterator;
+
+private:
+ friend class Chunk<ELFSegment, MCLD_SEGMENTS_PER_OUTPUT>;
+ ELFSegment();
+ ELFSegment(uint32_t pType, uint32_t pFlag = llvm::ELF::PF_R);
+
public:
- ELFSegment(uint32_t pType,
- uint32_t pFlag = llvm::ELF::PF_R,
- uint64_t pOffset = 0,
- uint64_t pVaddr = 0,
- uint64_t pPaddr = 0,
- uint64_t pFilesz = 0,
- uint64_t pMemsz = 0,
- uint64_t pAlign = 0,
- uint64_t pMaxSectAlign = 0);
~ELFSegment();
/// ----- iterators ----- ///
- sect_iterator begin() { return m_SectionList.begin(); }
- const_sect_iterator begin() const { return m_SectionList.begin(); }
- sect_iterator end() { return m_SectionList.end(); }
- const_sect_iterator end() const { return m_SectionList.end(); }
+ iterator begin() { return m_SectionList.begin(); }
+ const_iterator begin() const { return m_SectionList.begin(); }
+ iterator end() { return m_SectionList.end(); }
+ const_iterator end() const { return m_SectionList.end(); }
+
+ reverse_iterator rbegin() { return m_SectionList.rbegin(); }
+ const_reverse_iterator rbegin() const { return m_SectionList.rbegin(); }
+ reverse_iterator rend() { return m_SectionList.rend(); }
+ const_reverse_iterator rend() const { return m_SectionList.rend(); }
LDSection* front() { return m_SectionList.front(); }
const LDSection* front() const { return m_SectionList.front(); }
@@ -52,35 +59,20 @@
const LDSection* back() const { return m_SectionList.back(); }
/// ----- observers ----- ///
- uint32_t type() const
- { return m_Type; }
+ uint32_t type() const { return m_Type; }
+ uint64_t offset() const { return m_Offset; }
+ uint64_t vaddr() const { return m_Vaddr; }
+ uint64_t paddr() const { return m_Paddr; }
+ uint64_t filesz() const { return m_Filesz; }
+ uint64_t memsz() const { return m_Memsz; }
+ uint32_t flag() const { return m_Flag; }
+ uint64_t align() const { return std::max(m_Align, m_MaxSectionAlign); }
- uint64_t offset() const
- { return m_Offset; }
+ size_t size() const { return m_SectionList.size(); }
+ bool empty() const { return m_SectionList.empty(); }
- uint64_t vaddr() const
- { return m_Vaddr; }
-
- uint64_t paddr() const
- { return m_Paddr; }
-
- uint64_t filesz() const
- { return m_Filesz; }
-
- uint64_t memsz() const
- { return m_Memsz; }
-
- uint32_t flag() const
- { return m_Flag; }
-
- uint64_t align() const
- { return std::max(m_Align, m_MaxSectionAlign); }
-
- size_t numOfSections() const
- { return m_SectionList.size(); }
-
+ bool isLoadSegment() const;
bool isDataSegment() const;
-
bool isBssSegment() const;
/// ----- modifiers ----- ///
@@ -112,13 +104,14 @@
void setAlign(uint64_t pAlign)
{ m_Align = pAlign; }
- void addSection(LDSection* pSection)
- {
- assert(NULL != pSection);
- if (pSection->align() > m_MaxSectionAlign)
- m_MaxSectionAlign = pSection->align();
- m_SectionList.push_back(pSection);
- }
+ iterator insert(iterator pPos, LDSection* pSection);
+
+ void append(LDSection* pSection);
+
+ /* factory methods */
+ static ELFSegment* Create(uint32_t pType, uint32_t pFlag = llvm::ELF::PF_R);
+ static void Destroy(ELFSegment*& pSegment);
+ static void Clear();
private:
uint32_t m_Type; // Type of segment
@@ -130,7 +123,7 @@
uint64_t m_Memsz; // # of bytes in mem image of segment (may be 0)
uint64_t m_Align; // alignment constraint
uint64_t m_MaxSectionAlign; // max alignment of the sections in this segment
- std::vector<LDSection*> m_SectionList;
+ SectionList m_SectionList;
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFSegmentFactory.h b/include/mcld/LD/ELFSegmentFactory.h
index 5085a18..6df0389 100644
--- a/include/mcld/LD/ELFSegmentFactory.h
+++ b/include/mcld/LD/ELFSegmentFactory.h
@@ -6,38 +6,64 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELFSEGMENT_FACTORY_H
-#define MCLD_ELFSEGMENT_FACTORY_H
+#ifndef MCLD_LD_ELFSEGMENTFACTORY_H
+#define MCLD_LD_ELFSEGMENTFACTORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <mcld/Support/GCFactory.h>
-#include <mcld/LD/ELFSegment.h>
+
+#include <llvm/Support/DataTypes.h>
+#include <llvm/Support/ELF.h>
+#include <vector>
namespace mcld
{
+class ELFSegment;
+class LDSection;
+
/** \class ELFSegmentFactory
* \brief provide the interface to create and delete an ELFSegment
*/
-class ELFSegmentFactory : public GCFactory<ELFSegment, 0>
+class ELFSegmentFactory
{
public:
- /// ELFSegmentFactory - the factory of ELFSegment
- /// pNum is the magic number of the ELF segments in the output
- ELFSegmentFactory(size_t pNum);
- ~ELFSegmentFactory();
+ typedef std::vector<ELFSegment*> Segments;
+ typedef Segments::const_iterator const_iterator;
+ typedef Segments::iterator iterator;
+
+ const_iterator begin() const { return m_Segments.begin(); }
+ iterator begin() { return m_Segments.begin(); }
+ const_iterator end() const { return m_Segments.end(); }
+ iterator end() { return m_Segments.end(); }
+
+ const ELFSegment* front() const { return m_Segments.front(); }
+ ELFSegment* front() { return m_Segments.front(); }
+ const ELFSegment* back() const { return m_Segments.back(); }
+ ELFSegment* back() { return m_Segments.back(); }
+
+ size_t size() const { return m_Segments.size(); }
+
+ bool empty() const { return m_Segments.empty(); }
+
+ iterator find(uint32_t pType, uint32_t pFlagSet, uint32_t pFlagClear);
+
+ const_iterator
+ find(uint32_t pType, uint32_t pFlagSet, uint32_t pFlagClear) const;
+
+ iterator find(uint32_t pType, const LDSection* pSection);
+
+ const_iterator find(uint32_t pType, const LDSection* pSection) const;
/// produce - produce an empty ELF segment information.
/// this function will create an ELF segment
/// @param pType - p_type in ELF program header
ELFSegment* produce(uint32_t pType, uint32_t pFlag = llvm::ELF::PF_R);
- ELFSegment*
- find(uint32_t pType, uint32_t pFlagSet, uint32_t pFlagClear);
+ void erase(iterator pSegment);
- const ELFSegment*
- find(uint32_t pType, uint32_t pFlagSet, uint32_t pFlagClear) const;
+private:
+ Segments m_Segments;
};
} // namespace of mcld
diff --git a/include/mcld/LD/EhFrame.h b/include/mcld/LD/EhFrame.h
index c067746..6663d0f 100644
--- a/include/mcld/LD/EhFrame.h
+++ b/include/mcld/LD/EhFrame.h
@@ -6,23 +6,30 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_EH_FRAME_H
-#define MCLD_LD_EH_FRAME_H
+#ifndef MCLD_LD_EHFRAME_H
+#define MCLD_LD_EHFRAME_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <mcld/Config/Config.h>
#include <mcld/Fragment/RegionFragment.h>
-#include <mcld/Fragment/NullFragment.h>
+#include <mcld/LD/SectionData.h>
#include <mcld/Support/Allocators.h>
+#include <llvm/ADT/StringRef.h>
+#include <list>
+#include <map>
+#include <set>
#include <vector>
namespace mcld {
+class Input;
+class Module;
class LDSection;
-class SectionData;
+class ObjectLinker;
+class Relocation;
/** \class EhFrame
* \brief EhFrame represents .eh_frame section
@@ -41,53 +48,128 @@
EhFrame& operator=(const EhFrame&); // DO NOT IMPLEMENT
public:
+ enum RecordType {
+ RECORD_UNKNOWN,
+ RECORD_INPUT,
+ RECORD_GENERATED
+ };
+
+ class CIE;
+ class FDE;
+
+ typedef std::vector<CIE*> CIEList;
+ typedef CIEList::iterator cie_iterator;
+ typedef CIEList::const_iterator const_cie_iterator;
+
+ typedef std::list<FDE*> FDEList;
+ typedef FDEList::iterator fde_iterator;
+ typedef FDEList::const_iterator const_fde_iterator;
+
+ typedef std::map</*offset*/size_t, CIE*> CIEMap;
+
+ // A super class of CIE and FDE, containing the same part
+ class Record : public RegionFragment
+ {
+ public:
+ Record(llvm::StringRef pRegion);
+ virtual ~Record();
+
+ const llvm::StringRef getRegion() const { return RegionFragment::getRegion(); }
+ llvm::StringRef getRegion() { return RegionFragment::getRegion(); }
+ virtual RecordType getRecordType() const { return RECORD_UNKNOWN; }
+
+ private:
+ Record(const Record&); // DO NOT IMPLEMENT
+ Record& operator=(const Record&); // DO NOT IMPLEMENT
+ };
+
/** \class CIE
* \brief Common Information Entry.
* The CIE structure refers to LSB Core Spec 4.1, chap.10.6. Exception Frames.
*/
- class CIE : public RegionFragment
+ class CIE : public Record
{
public:
- CIE(MemoryRegion& pRegion);
+ CIE(llvm::StringRef pRegion);
+ ~CIE();
+
+ virtual RecordType getRecordType() const { return RECORD_INPUT; }
void setFDEEncode(uint8_t pEncode) { m_FDEEncode = pEncode; }
uint8_t getFDEEncode() const { return m_FDEEncode; }
+ void setMergeable(bool pVal = true) { m_Mergeable = pVal; }
+ virtual bool getMergeable() const { return m_Mergeable; }
+
+ void setRelocation(const Relocation& pReloc) { m_pReloc = &pReloc; }
+ const Relocation* getRelocation() const { return m_pReloc; }
+
+ void setPersonalityOffset(uint64_t pOffset) { m_PersonalityOffset = pOffset; }
+ uint64_t getPersonalityOffset() const { return m_PersonalityOffset; }
+
+ void setPersonalityName(const std::string& pStr) { m_PersonalityName = pStr; }
+ const std::string& getPersonalityName() const { return m_PersonalityName; }
+
+ void setAugmentationData(const std::string& pStr) { m_AugmentationData = pStr; }
+ const std::string& getAugmentationData() const { return m_AugmentationData; }
+
+ void add(FDE& pFDE) { m_FDEs.push_back(&pFDE); }
+ void remove(FDE& pFDE) { m_FDEs.remove(&pFDE); }
+ void clearFDEs() { m_FDEs.clear(); }
+ size_t numOfFDEs() const { return m_FDEs.size(); }
+
+ const_fde_iterator begin() const { return m_FDEs.begin(); }
+ fde_iterator begin() { return m_FDEs.begin(); }
+ const_fde_iterator end() const { return m_FDEs.end(); }
+ fde_iterator end() { return m_FDEs.end(); }
+
private:
uint8_t m_FDEEncode;
+ bool m_Mergeable;
+ const Relocation* m_pReloc;
+ uint64_t m_PersonalityOffset;
+ std::string m_PersonalityName;
+ std::string m_AugmentationData;
+ FDEList m_FDEs;
};
/** \class FDE
* \brief Frame Description Entry
* The FDE structure refers to LSB Core Spec 4.1, chap.10.6. Exception Frames.
*/
- class FDE : public RegionFragment
+ class FDE : public Record
{
public:
- FDE(MemoryRegion& pRegion,
- const CIE& pCIE,
- uint32_t pDataStart);
+ FDE(llvm::StringRef pRegion, CIE& pCIE);
+ ~FDE();
- const CIE& getCIE() const { return m_CIE; }
-
- uint32_t getDataStart() const { return m_DataStart; }
+ void setCIE(CIE& pCIE);
+ const CIE& getCIE() const { return *m_pCIE; }
+ CIE& getCIE() { return *m_pCIE; }
private:
- const CIE& m_CIE;
- uint32_t m_DataStart;
+ CIE* m_pCIE; // Referenced CIE may change when merging.
};
- typedef std::vector<CIE*> CIEList;
+ // These are created for PLT
+ class GeneratedCIE : public CIE
+ {
+ public:
+ GeneratedCIE(llvm::StringRef pRegion);
+ ~GeneratedCIE();
- // cie_iterator and const_cie_iterator must be a kind of random access iterator
- typedef CIEList::iterator cie_iterator;
- typedef CIEList::const_iterator const_cie_iterator;
+ virtual RecordType getRecordType() const { return RECORD_GENERATED; }
+ virtual bool getMergeable() const { return true; }
+ };
- typedef std::vector<FDE*> FDEList;
+ class GeneratedFDE : public FDE
+ {
+ public:
+ GeneratedFDE(llvm::StringRef pRegion, CIE& pCIE);
+ ~GeneratedFDE();
- // fde_iterator and const_fde_iterator must be a kind of random access iterator
- typedef FDEList::iterator fde_iterator;
- typedef FDEList::const_iterator const_fde_iterator;
+ virtual RecordType getRecordType() const { return RECORD_GENERATED; }
+ };
public:
static EhFrame* Create(LDSection& pSection);
@@ -97,7 +179,7 @@
static void Clear();
/// merge - move all data from pOther to this object.
- EhFrame& merge(EhFrame& pOther);
+ EhFrame& merge(const Input& pInput, EhFrame& pInFrame);
const LDSection& getSection() const;
LDSection& getSection();
@@ -106,17 +188,13 @@
SectionData* getSectionData() { return m_pSectionData; }
// ----- fragment ----- //
- /// addFragment - when we start treating CIEs and FDEs as regular fragments,
- /// we call this function instead of addCIE() and addFDE().
- void addFragment(RegionFragment& pFrag);
-
- void addFragment(NullFragment& pFrag);
+ void addFragment(Fragment& pFrag);
/// addCIE - add a CIE entry in EhFrame
- void addCIE(CIE& pCIE);
+ void addCIE(CIE& pCIE, bool pAlsoAddFragment = true);
/// addFDE - add a FDE entry in EhFrame
- void addFDE(FDE& pFDE);
+ void addFDE(FDE& pFDE, bool pAlsoAddFragment = true);
// ----- CIE ----- //
const_cie_iterator cie_begin() const { return m_CIEs.begin(); }
@@ -129,29 +207,54 @@
const CIE& cie_back () const { return *m_CIEs.back(); }
CIE& cie_back () { return *m_CIEs.back(); }
+ bool emptyCIEs() const { return m_CIEs.empty(); }
size_t numOfCIEs() const { return m_CIEs.size(); }
+ size_t numOfFDEs() const;
- // ----- FDE ----- //
- const_fde_iterator fde_begin() const { return m_FDEs.begin(); }
- fde_iterator fde_begin() { return m_FDEs.begin(); }
- const_fde_iterator fde_end () const { return m_FDEs.end(); }
- fde_iterator fde_end () { return m_FDEs.end(); }
+ const CIEMap& getCIEMap() const { return m_FoundCIEs; }
+ CIEMap& getCIEMap() { return m_FoundCIEs; }
- const FDE& fde_front() const { return *m_FDEs.front(); }
- FDE& fde_front() { return *m_FDEs.front(); }
- const FDE& fde_back () const { return *m_FDEs.back(); }
- FDE& fde_back () { return *m_FDEs.back(); }
+public:
+ size_t computeOffsetSize();
- size_t numOfFDEs() const { return m_FDEs.size(); }
+ /// getDataStartOffset - Get the offset after length and ID field.
+ /// The offset is 8byte for 32b, and 16byte for 64b.
+ /// We can just use "BITCLASS/4" to represent offset.
+ template <size_t BITCLASS>
+ static size_t getDataStartOffset() { return BITCLASS / 4; }
+
+private:
+ // We needs to check if it is mergeable and check personality name
+ // before merging them. The important note is we must do this after
+ // ALL readSections done, that is the reason why we don't check this
+ // immediately when reading.
+ void setupAttributes(const LDSection* reloc_sect);
+ void removeDiscardedFDE(CIE& pCIE, const LDSection* pRelocEhFrameSect);
+
+private:
+ void removeAndUpdateCIEForFDE(EhFrame& pInFrame, CIE& pInCIE, CIE& pOutCIE,
+ const LDSection* reloc_sect);
+ void moveInputFragments(EhFrame& pInFrame);
+ void moveInputFragments(EhFrame& pInFrame, CIE& pInCIE, CIE* pOutCIE = 0);
private:
LDSection* m_pSection;
SectionData* m_pSectionData;
+ // Each eh_frame has a list of CIE, and each CIE has a list of FDE
+ // pointing to the CIE itself. This is used by management when we are
+ // processing eh_frame merge.
+ // However, don't forget we need to handle the Fragments inside SectionData
+ // correctly since they are truly used when output emission.
CIEList m_CIEs;
- FDEList m_FDEs;
+
+ // We need this map to find the corresponding CIE for FDE. Not all FDE point
+ // to the nearest CIE.
+ CIEMap m_FoundCIEs;
};
+bool operator==(const EhFrame::CIE&, const EhFrame::CIE&);
+
} // namespace of mcld
#endif
diff --git a/include/mcld/LD/EhFrameHdr.h b/include/mcld/LD/EhFrameHdr.h
index 3a5971d..2d7b0e9 100644
--- a/include/mcld/LD/EhFrameHdr.h
+++ b/include/mcld/LD/EhFrameHdr.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_EHFRAMEHDR_H
-#define MCLD_EHFRAMEHDR_H
+#ifndef MCLD_LD_EHFRAMEHDR_H
+#define MCLD_LD_EHFRAMEHDR_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -15,11 +15,11 @@
#include <cassert>
#include <mcld/LD/EhFrame.h>
+#include <mcld/Support/FileOutputBuffer.h>
namespace mcld {
class LDSection;
-class MemoryArea;
-class MemoryRegion;
+class FileOutputBuffer;
/** \class EhFrameHdr
* \brief EhFrameHdr represents .eh_frame_hdr section.
@@ -47,13 +47,14 @@
/// emitOutput - write out eh_frame_hdr
template<size_t size>
- void emitOutput(MemoryArea& pOutput)
+ void emitOutput(FileOutputBuffer& pOutput)
{ assert(false && "Call invalid EhFrameHdr::emitOutput"); }
private:
/// computePCBegin - return the address of FDE's pc
/// @ref binutils gold: ehframe.cc:222
- uint32_t computePCBegin(const EhFrame::FDE& pFDE, const MemoryRegion& pEhFrameRegion);
+ uint32_t computePCBegin(const EhFrame::FDE& pFDE,
+ const MemoryRegion& pEhFrameRegion);
private:
/// .eh_frame_hdr section
@@ -68,7 +69,7 @@
//===----------------------------------------------------------------------===//
/// emitOutput - write out eh_frame_hdr
template<>
-void EhFrameHdr::emitOutput<32>(MemoryArea& pOutput);
+void EhFrameHdr::emitOutput<32>(FileOutputBuffer& pOutput);
} // namespace of mcld
diff --git a/include/mcld/LD/EhFrameReader.h b/include/mcld/LD/EhFrameReader.h
index 1ac0351..509debf 100644
--- a/include/mcld/LD/EhFrameReader.h
+++ b/include/mcld/LD/EhFrameReader.h
@@ -6,17 +6,18 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_EH_FRAME_READER_H
-#define MCLD_EH_FRAME_READER_H
+#ifndef MCLD_LD_EHFRAMEREADER_H
+#define MCLD_LD_EHFRAMEREADER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <mcld/Support/MemoryRegion.h>
+#include <mcld/LD/EhFrame.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/DataTypes.h>
namespace mcld {
class Input;
-class EhFrame;
class LDSection;
/** \class EhFrameReader
@@ -28,8 +29,8 @@
class EhFrameReader
{
public:
- typedef const uint8_t* ConstAddress;
- typedef uint8_t* Address;
+ typedef const char* ConstAddress;
+ typedef char* Address;
public:
/// read - read an .eh_frame section and create the corresponding
@@ -70,29 +71,29 @@
/// @param pSection - the input .eh_frame section
/// @param pRegion - the memory region that needs to handle with.
typedef bool (*Action)(EhFrame& pEhFrame,
- MemoryRegion& pRegion,
+ llvm::StringRef pRegion,
const Token& pToken);
private:
/// scan - scan pData from pHandler for a token.
- template<bool SAME_ENDIAN> Token
- scan(ConstAddress pHandler, uint64_t pOffset, const MemoryRegion& pData) const;
+ template<bool SAME_ENDIAN> Token scan(ConstAddress pHandler,
+ uint64_t pOffset,
+ llvm::StringRef pData) const;
static bool addCIE(EhFrame& pEhFrame,
- MemoryRegion& pRegion,
+ llvm::StringRef pRegion,
const Token& pToken);
static bool addFDE(EhFrame& pEhFrame,
- MemoryRegion& pRegion,
+ llvm::StringRef pRegion,
const Token& pToken);
static bool addTerm(EhFrame& pEhFrame,
- MemoryRegion& pRegion,
+ llvm::StringRef pRegion,
const Token& pToken);
static bool reject(EhFrame& pEhFrame,
- MemoryRegion& pRegion,
+ llvm::StringRef pRegion,
const Token& pToken);
-
};
template<> bool
@@ -101,7 +102,7 @@
template<> EhFrameReader::Token
EhFrameReader::scan<true>(ConstAddress pHandler,
uint64_t pOffset,
- const MemoryRegion& pData) const;
+ llvm::StringRef pData) const;
} // namespace of mcld
diff --git a/include/mcld/LD/GNUArchiveReader.h b/include/mcld/LD/GNUArchiveReader.h
index 7a33ff4..1c2e10a 100644
--- a/include/mcld/LD/GNUArchiveReader.h
+++ b/include/mcld/LD/GNUArchiveReader.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_GNU_ARCHIVE_READER_H
-#define MCLD_GNU_ARCHIVE_READER_H
+#ifndef MCLD_LD_GNUARCHIVEREADER_H
+#define MCLD_LD_GNUARCHIVEREADER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -20,8 +20,8 @@
class Module;
class Input;
class ELFObjectReader;
-class MemoryAreaFactory;
class Archive;
+class LinkerConfig;
/** \class GNUArchiveReader
* \brief GNUArchiveReader reads GNU archive files.
@@ -35,10 +35,10 @@
/// readArchive - read an archive, include the needed members, and build up
/// the subtree
- bool readArchive(Archive& pArchive);
+ bool readArchive(const LinkerConfig& pConfig, Archive& pArchive);
/// isMyFormat
- bool isMyFormat(Input& input) const;
+ bool isMyFormat(Input& input, bool &pContinue) const;
private:
/// isArchive
@@ -78,13 +78,16 @@
/// includeMember - include the object member in the given file offset, and
/// return the size of the object
+ /// @param pConfig - LinkerConfig
/// @param pArchiveRoot - the archive root
/// @param pFileOffset - file offset of the member header in the archive
- size_t includeMember(Archive& pArchiveRoot, uint32_t pFileOffset);
+ size_t includeMember(const LinkerConfig& pConfig,
+ Archive& pArchiveRoot,
+ uint32_t pFileOffset);
/// includeAllMembers - include all object members. This is called if
/// --whole-archive is the attribute for this archive file.
- bool includeAllMembers(Archive& pArchive);
+ bool includeAllMembers(const LinkerConfig& pConfig, Archive& pArchive);
private:
Module& m_Module;
diff --git a/include/mcld/LD/GarbageCollection.h b/include/mcld/LD/GarbageCollection.h
new file mode 100644
index 0000000..3476cd1
--- /dev/null
+++ b/include/mcld/LD/GarbageCollection.h
@@ -0,0 +1,94 @@
+//===- GarbageCollection.h ------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_LD_GARBAGECOLLECTION_H
+#define MCLD_LD_GARBAGECOLLECTION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <map>
+#include <set>
+#include <vector>
+
+namespace mcld {
+
+class LDSection;
+class LinkerConfig;
+class Module;
+class TargetLDBackend;
+
+/** \class GarbageCollection
+ * \brief Implementation of garbage collection for --gc-section.
+ * @ref GNU gold, gc.
+ */
+class GarbageCollection
+{
+public:
+ typedef std::set<const LDSection*> SectionListTy;
+ typedef std::vector<const LDSection*> SectionVecTy;
+
+ /** \class SectionReachedListMap
+ * \brief Map the section to the list of sections which it can reach directly
+ */
+ class SectionReachedListMap
+ {
+ public:
+ SectionReachedListMap() {}
+
+ /// addReference - add a reference from pFrom to pTo
+ void addReference(const LDSection& pFrom, const LDSection& pTo);
+
+ /// getReachedList - get the list of sections which can be reached by
+ /// pSection, create one if the list has not existed
+ SectionListTy& getReachedList(const LDSection& pSection);
+
+ /// findReachedList - find the list of sections which can be reached by
+ /// pSection, return NULL if the list not exists
+ SectionListTy* findReachedList(const LDSection& pSection);
+
+ private:
+ typedef std::map<const LDSection*, SectionListTy> ReachedSectionsTy;
+
+ private:
+ /// m_ReachedSections - map a section to the reachable sections list
+ ReachedSectionsTy m_ReachedSections;
+ };
+
+public:
+ GarbageCollection(const LinkerConfig& pConfig,
+ const TargetLDBackend& pBackend,
+ Module& pModule);
+ ~GarbageCollection();
+
+ /// run - do garbage collection
+ bool run();
+
+private:
+ void setUpReachedSections();
+ void findReferencedSections(SectionVecTy& pEntry);
+ void getEntrySections(SectionVecTy& pEntry);
+ void stripSections();
+
+private:
+ /// m_SectionReachedListMap - map the section to the list of sections which it
+ /// can reach directly
+ SectionReachedListMap m_SectionReachedListMap;
+
+ /// m_ReferencedSections - a list of sections which can be reached from entry
+ SectionListTy m_ReferencedSections;
+
+ const LinkerConfig& m_Config;
+ const TargetLDBackend& m_Backend;
+ Module& m_Module;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/Group.h b/include/mcld/LD/Group.h
index 31c4a68..30e8f63 100644
--- a/include/mcld/LD/Group.h
+++ b/include/mcld/LD/Group.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef LD_GROUP_H
-#define LD_GROUP_H
+#ifndef MCLD_LD_GROUP_H
+#define MCLD_LD_GROUP_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/GroupReader.h b/include/mcld/LD/GroupReader.h
index 01178a0..fa1e182 100644
--- a/include/mcld/LD/GroupReader.h
+++ b/include/mcld/LD/GroupReader.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_GROUPREADER_H
-#define MCLD_GROUPREADER_H
+#ifndef MCLD_LD_GROUPREADER_H
+#define MCLD_LD_GROUPREADER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -43,6 +43,7 @@
/// readGroup - handle the input sub-tree wich its root is pRoot
/// @param pRoot - the root Group node of the sub-tree
bool readGroup(Module::input_iterator pRoot,
+ Module::input_iterator pEnd,
InputBuilder& pBuilder,
const LinkerConfig& pConfig);
diff --git a/include/mcld/LD/LDContext.h b/include/mcld/LD/LDContext.h
index 3ab6ce1..c9f30ae 100644
--- a/include/mcld/LD/LDContext.h
+++ b/include/mcld/LD/LDContext.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LDCONTEXT_H
-#define MCLD_LDCONTEXT_H
+#ifndef MCLD_LD_LDCONTEXT_H
+#define MCLD_LD_LDCONTEXT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -72,6 +72,12 @@
void addSymbol(LDSymbol* pSym)
{ m_SymTab.push_back(pSym); }
+ const_sym_iterator symTabBegin() const { return m_SymTab.begin(); }
+ sym_iterator symTabBegin() { return m_SymTab.begin(); }
+
+ const_sym_iterator symTabEnd() const { return m_SymTab.end(); }
+ sym_iterator symTabEnd() { return m_SymTab.end(); }
+
// ----- relocations ----- //
const_sect_iterator relocSectBegin() const { return m_RelocSections.begin(); }
sect_iterator relocSectBegin() { return m_RelocSections.begin(); }
diff --git a/include/mcld/LD/LDFileFormat.h b/include/mcld/LD/LDFileFormat.h
index 4fa58ce..fb5ab63 100644
--- a/include/mcld/LD/LDFileFormat.h
+++ b/include/mcld/LD/LDFileFormat.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LDFILE_FORMAT_H
-#define MCLD_LDFILE_FORMAT_H
+#ifndef MCLD_LD_LDFILEFORMAT_H
+#define MCLD_LD_LDFILEFORMAT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/LDReader.h b/include/mcld/LD/LDReader.h
index 4fde9f0..38bf24d 100644
--- a/include/mcld/LD/LDReader.h
+++ b/include/mcld/LD/LDReader.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_READER_INTERFACE_H
-#define MCLD_READER_INTERFACE_H
+#ifndef MCLD_LD_LDREADER_H
+#define MCLD_LD_LDREADER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -37,7 +37,7 @@
public:
virtual ~LDReader() { }
- virtual bool isMyFormat(Input& pInput) const = 0;
+ virtual bool isMyFormat(Input& pInput, bool &pContinue) const = 0;
};
diff --git a/include/mcld/LD/LDSymbol.h b/include/mcld/LD/LDSymbol.h
index b40213c..bebdd18 100644
--- a/include/mcld/LD/LDSymbol.h
+++ b/include/mcld/LD/LDSymbol.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_SYMBOL_H
-#define MCLD_LD_SYMBOL_H
+#ifndef MCLD_LD_LDSYMBOL_H
+#define MCLD_LD_LDSYMBOL_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -19,7 +19,12 @@
#include <mcld/LD/ResolveInfo.h>
#include <mcld/Support/Allocators.h>
-#include <llvm/Support/ManagedStatic.h>
+namespace llvm {
+
+// forware declaration
+template<class T> void* object_creator();
+
+} // namespace of llvm
namespace mcld {
diff --git a/include/mcld/LD/MsgHandler.h b/include/mcld/LD/MsgHandler.h
index 9b1ed80..62def8e 100644
--- a/include/mcld/LD/MsgHandler.h
+++ b/include/mcld/LD/MsgHandler.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_MESSAGE_HANDLER_H
-#define MCLD_MESSAGE_HANDLER_H
+#ifndef MCLD_LD_MSGHANDLER_H
+#define MCLD_LD_MSGHANDLER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/NamePool.h b/include/mcld/LD/NamePool.h
index 32354ea..7a8f816 100644
--- a/include/mcld/LD/NamePool.h
+++ b/include/mcld/LD/NamePool.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_NAME_POOL_H
-#define MCLD_NAME_POOL_H
+#ifndef MCLD_LD_NAMEPOOL_H
+#define MCLD_LD_NAMEPOOL_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -38,7 +38,14 @@
class NamePool : private Uncopyable
{
public:
- typedef HashTable<ResolveInfo, hash::StringHash<hash::ELF> > Table;
+ typedef HashTable<ResolveInfo, hash::StringHash<hash::DJB> > Table;
+ typedef Table::iterator syminfo_iterator;
+ typedef Table::const_iterator const_syminfo_iterator;
+
+ typedef GCFactory<ResolveInfo*, 128> FreeInfoSet;
+ typedef FreeInfoSet::iterator freeinfo_iterator;
+ typedef FreeInfoSet::const_iterator const_freeinfo_iterator;
+
typedef size_t size_type;
public:
@@ -56,7 +63,7 @@
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
ResolveInfo::Visibility pVisibility = ResolveInfo::Default);
-
+
/// insertSymbol - insert a symbol and resolve the symbol immediately
/// @param pOldInfo - if pOldInfo is not NULL, the old ResolveInfo being
/// overriden is kept in pOldInfo.
@@ -69,6 +76,7 @@
ResolveInfo::Desc pDesc,
ResolveInfo::Binding pBinding,
ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
ResolveInfo::Visibility pVisibility,
ResolveInfo* pOldInfo,
Resolver::Result& pResult);
@@ -93,15 +101,39 @@
bool empty() const
{ return m_Table.empty(); }
+ // syminfo_iterator - traverse the ResolveInfo in the resolved HashTable
+ syminfo_iterator syminfo_begin()
+ { return m_Table.begin(); }
+
+ syminfo_iterator syminfo_end()
+ { return m_Table.end(); }
+
+ const_syminfo_iterator syminfo_begin() const
+ { return m_Table.begin(); }
+
+ const_syminfo_iterator syminfo_end() const
+ { return m_Table.end(); }
+
+ // freeinfo_iterator - traverse the ResolveInfo those do not need to be
+ // resolved, for example, local symbols
+ freeinfo_iterator freeinfo_begin()
+ { return m_FreeInfoSet.begin(); }
+
+ freeinfo_iterator freeinfo_end()
+ { return m_FreeInfoSet.end(); }
+
+ const_freeinfo_iterator freeinfo_begin() const
+ { return m_FreeInfoSet.begin(); }
+
+ const_freeinfo_iterator freeinfo_end() const
+ { return m_FreeInfoSet.end(); }
+
// ----- capacity ----- //
void reserve(size_type pN);
size_type capacity() const;
private:
- typedef GCFactory<ResolveInfo*, 128> FreeInfoSet;
-
-private:
Resolver* m_pResolver;
Table m_Table;
FreeInfoSet m_FreeInfoSet;
diff --git a/include/mcld/LD/ObjectReader.h b/include/mcld/LD/ObjectReader.h
index 2ca3173..34427f8 100644
--- a/include/mcld/LD/ObjectReader.h
+++ b/include/mcld/LD/ObjectReader.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_OBJECT_READER_H
-#define MCLD_OBJECT_READER_H
+#ifndef MCLD_LD_OBJECTREADER_H
+#define MCLD_LD_OBJECTREADER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -29,7 +29,7 @@
class ObjectReader : public LDReader
{
protected:
- typedef HashTable<ResolveInfo, hash::StringHash<hash::ELF> > GroupSignatureMap;
+ typedef HashTable<ResolveInfo, hash::StringHash<hash::DJB> > GroupSignatureMap;
protected:
ObjectReader()
diff --git a/include/mcld/LD/ObjectWriter.h b/include/mcld/LD/ObjectWriter.h
index c1dcac6..2a42aed 100644
--- a/include/mcld/LD/ObjectWriter.h
+++ b/include/mcld/LD/ObjectWriter.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_OBJECT_WRITER_INTERFACE_H
-#define MCLD_OBJECT_WRITER_INTERFACE_H
+#ifndef MCLD_LD_OBJECTWRITER_H
+#define MCLD_LD_OBJECTWRITER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -16,7 +16,7 @@
namespace mcld {
class Module;
-class MemoryArea;
+class FileOutputBuffer;
/** \class ObjectWriter
* \brief ObjectWriter provides a common interface for object file writers.
@@ -29,7 +29,10 @@
public:
virtual ~ObjectWriter();
- virtual llvm::error_code writeObject(Module& pModule, MemoryArea& pOutput) = 0;
+ virtual llvm::error_code writeObject(Module& pModule,
+ FileOutputBuffer& pOutput) = 0;
+
+ virtual size_t getOutputSize(const Module& pModule) const = 0;
};
} // namespace of mcld
diff --git a/include/mcld/LD/RelocData.h b/include/mcld/LD/RelocData.h
index b53151a..68bc7e1 100644
--- a/include/mcld/LD/RelocData.h
+++ b/include/mcld/LD/RelocData.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_RELOCATION_DATA_H
-#define MCLD_RELOCATION_DATA_H
+#ifndef MCLD_LD_RELOCDATA_H
+#define MCLD_LD_RELOCDATA_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -21,6 +21,8 @@
#include <llvm/ADT/ilist_node.h>
#include <llvm/Support/DataTypes.h>
+#include <list>
+
namespace mcld {
class LDSection;
@@ -73,6 +75,7 @@
bool empty() const { return m_Relocations.empty(); }
RelocData& append(Relocation& pRelocation);
+ Relocation& remove(Relocation& pRelocation);
reference front () { return m_Relocations.front(); }
const_reference front () const { return m_Relocations.front(); }
@@ -88,6 +91,18 @@
const_reverse_iterator rend () const { return m_Relocations.rend(); }
reverse_iterator rend () { return m_Relocations.rend(); }
+ template<class Comparator> void sort(Comparator pComparator) {
+ /* FIXME: use llvm::iplist::sort */
+ std::list<Relocation*> relocs;
+ for (iterator it = begin(), ie = end(); it != ie; ++it)
+ relocs.push_back(it);
+ relocs.sort(pComparator);
+ m_Relocations.clear();
+ for (std::list<Relocation*>::iterator it = relocs.begin(),
+ ie = relocs.end(); it != ie; ++it)
+ m_Relocations.push_back(*it);
+ }
+
private:
RelocationListType m_Relocations;
LDSection* m_pSection;
diff --git a/include/mcld/LD/Relocator.h b/include/mcld/LD/Relocator.h
index 54ea7e8..2828a5b 100644
--- a/include/mcld/LD/Relocator.h
+++ b/include/mcld/LD/Relocator.h
@@ -61,10 +61,21 @@
/// @param pReloc - a read in relocation entry
/// @param pInputSym - the input LDSymbol of relocation target symbol
/// @param pSection - the section of relocation applying target
+ /// @param pInput - the input file of relocation
virtual void scanRelocation(Relocation& pReloc,
IRBuilder& pBuilder,
Module& pModule,
- LDSection& pSection) = 0;
+ LDSection& pSection,
+ Input& pInput) = 0;
+
+ /// issueUndefRefError - Provides a basic version for undefined reference dump.
+ /// It will handle the filename and function name automatically.
+ /// @param pReloc - a read in relocation entry
+ /// @param pSection - the section of relocation applying target
+ /// @ param pInput - the input file of relocation
+ virtual void issueUndefRef(Relocation& pReloc,
+ LDSection& pSection,
+ Input& pInput);
/// initializeScan - do initialization before scan relocations in pInput
/// @return - return true for initialization success
diff --git a/include/mcld/LD/ResolveInfo.h b/include/mcld/LD/ResolveInfo.h
index 6f28169..9616719 100644
--- a/include/mcld/LD/ResolveInfo.h
+++ b/include/mcld/LD/ResolveInfo.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_RESOLVE_INFO_H
-#define MCLD_RESOLVE_INFO_H
+#ifndef MCLD_LD_RESOLVEINFO_H
+#define MCLD_LD_RESOLVEINFO_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -18,6 +18,7 @@
namespace mcld {
class LDSymbol;
+class LinkerConfig;
/** \class ResolveInfo
* \brief ResolveInfo records the information about how to resolve a symbol.
@@ -142,6 +143,10 @@
m_BitField |= indirect_flag;
}
+ /// setInDyn - set if the symbol has been seen in the dynamic objects. Once
+ /// InDyn set, then it won't be set back to false
+ void setInDyn();
+
// ----- observers ----- //
bool isNull() const;
@@ -167,6 +172,8 @@
bool isIndirect() const;
+ bool isInDyn() const;
+
uint32_t type() const;
uint32_t desc() const;
@@ -207,6 +214,9 @@
uint32_t bitfield() const
{ return m_BitField; }
+ // shouldForceLocal - check if this symbol should be forced to local
+ bool shouldForceLocal(const LinkerConfig& pConfig);
+
// ----- For HashTable ----- //
bool compare(const key_type& pKey);
@@ -236,7 +246,11 @@
static const uint32_t RESERVED_OFFSET = 12;
static const uint32_t RESERVED_MASK = 0xF << RESERVED_OFFSET;
- static const uint32_t NAME_LENGTH_OFFSET = 16;
+
+ static const uint32_t IN_DYN_OFFSET = 16;
+ static const uint32_t IN_DYN_MASK = 1 << IN_DYN_OFFSET;
+
+ static const uint32_t NAME_LENGTH_OFFSET = 17;
static const uint32_t INFO_MASK = 0xF;
static const uint32_t RESOLVE_MASK = 0xFFFF;
@@ -262,6 +276,7 @@
static const uint32_t file_flag = File << TYPE_OFFSET;
static const uint32_t string_flag = 0 << SYMBOL_OFFSET;
static const uint32_t symbol_flag = 1 << SYMBOL_OFFSET;
+ static const uint32_t indyn_flag = 1 << IN_DYN_OFFSET;
private:
ResolveInfo();
@@ -274,8 +289,8 @@
SymOrInfo m_Ptr;
/** m_BitField
- * 31 ... 16 15 12 11 10..7 6 .. 5 4 3 2 1 0
- * |length of m_Name|reserved|Symbol|Type |ELF visibility|Local|Com|Def|Dyn|Weak|
+ * 31 ... 17 16 15 12 11 10..7 6 .. 5 4 3 2 1 0
+ * |length of m_Name|InDyn|reserved|Symbol|Type |ELF visibility|Local|Com|Def|Dyn|Weak|
*/
uint32_t m_BitField;
char m_Name[];
diff --git a/include/mcld/LD/Resolver.h b/include/mcld/LD/Resolver.h
index d506a2d..069a167 100644
--- a/include/mcld/LD/Resolver.h
+++ b/include/mcld/LD/Resolver.h
@@ -6,13 +6,14 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_SYMBOL_RESOLVER_H
-#define MCLD_SYMBOL_RESOLVER_H
+#ifndef MCLD_LD_RESOLVER_H
+#define MCLD_LD_RESOLVER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <string>
#include <utility>
+#include <mcld/LD/LDSymbol.h>
namespace mcld
{
@@ -59,7 +60,7 @@
/// @param pNew the symbol which is used to replace pOld
virtual bool resolve(ResolveInfo & __restrict__ pOld,
const ResolveInfo & __restrict__ pNew,
- bool &pOverride) const = 0;
+ bool &pOverride, LDSymbol::ValueType pValue) const = 0;
/// resolveAgain - Can override by derived classes.
/// @return the pointer to resolved ResolveInfo
diff --git a/include/mcld/LD/SectionData.h b/include/mcld/LD/SectionData.h
index 4f58afa..0a74961 100644
--- a/include/mcld/LD/SectionData.h
+++ b/include/mcld/LD/SectionData.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_SECTION_DATA_H
-#define MCLD_LD_SECTION_DATA_H
+#ifndef MCLD_LD_SECTIONDATA_H
+#define MCLD_LD_SECTIONDATA_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/SectionSymbolSet.h b/include/mcld/LD/SectionSymbolSet.h
index 801fe37..fe814a7 100644
--- a/include/mcld/LD/SectionSymbolSet.h
+++ b/include/mcld/LD/SectionSymbolSet.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_SECTIONSYMBOLSET_H
-#define MCLD_SECTIONSYMBOLSET_H
+#ifndef MCLD_LD_SECTIONSYMBOLSET_H
+#define MCLD_LD_SECTIONSYMBOLSET_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/StaticResolver.h b/include/mcld/LD/StaticResolver.h
index 9fc6104..586e44d 100644
--- a/include/mcld/LD/StaticResolver.h
+++ b/include/mcld/LD/StaticResolver.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_STATIC_SYMBOL_RESOLVER_H
-#define MCLD_STATIC_SYMBOL_RESOLVER_H
+#ifndef MCLD_LD_STATICRESOLVER_H
+#define MCLD_LD_STATICRESOLVER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -111,7 +111,7 @@
/// @param pNew the symbol which is used to replace pOld
virtual bool resolve(ResolveInfo & __restrict__ pOld,
const ResolveInfo & __restrict__ pNew,
- bool &pOverride) const;
+ bool &pOverride, LDSymbol::ValueType pValue) const;
private:
inline unsigned int getOrdinate(const ResolveInfo& pInfo) const {
diff --git a/include/mcld/LD/StubFactory.h b/include/mcld/LD/StubFactory.h
index 8548e5a..4298c16 100644
--- a/include/mcld/LD/StubFactory.h
+++ b/include/mcld/LD/StubFactory.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_STUB_FACTORY_H
-#define MCLD_LD_STUB_FACTORY_H
+#ifndef MCLD_LD_STUBFACTORY_H
+#define MCLD_LD_STUBFACTORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LD/TextDiagnosticPrinter.h b/include/mcld/LD/TextDiagnosticPrinter.h
index 3e7d4c4..6400fa2 100644
--- a/include/mcld/LD/TextDiagnosticPrinter.h
+++ b/include/mcld/LD/TextDiagnosticPrinter.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_TEXT_DIAGNOSTIC_PRINTER_H
-#define MCLD_TEXT_DIAGNOSTIC_PRINTER_H
+#ifndef MCLD_LD_TEXTDIAGNOSTICPRINTER_H
+#define MCLD_LD_TEXTDIAGNOSTICPRINTER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Linker.h b/include/mcld/Linker.h
index 83eb295..80f6586 100644
--- a/include/mcld/Linker.h
+++ b/include/mcld/Linker.h
@@ -27,7 +27,7 @@
class ObjectLinker;
class FileHandle;
-class MemoryArea;
+class FileOutputBuffer;
/** \class Linker
* \brief Linker is a modular linker.
@@ -46,7 +46,7 @@
bool normalize(Module& pModule, IRBuilder& pBuilder);
/// resolve - To build up the topology of mcld::Module.
- bool resolve();
+ bool resolve(Module& pModule);
/// layout - To serialize the final result of the output mcld::Module.
bool layout();
@@ -54,15 +54,15 @@
/// link - A convenient way to resolve and to layout the output mcld::Module.
bool link(Module& pModule, IRBuilder& pBuilder);
- /// emit - To emit output mcld::Module to a output MemoryArea
- bool emit(MemoryArea& pOutput);
+ /// emit - To emit output mcld::Module to a FileOutputBuffer.
+ bool emit(FileOutputBuffer& pOutput);
/// emit - To open a file for output in pPath and to emit output mcld::Module
/// to the file.
- bool emit(const std::string& pPath);
+ bool emit(const Module& pModule, const std::string& pPath);
/// emit - To emit output mcld::Module in the pFileDescriptor.
- bool emit(int pFileDescriptor);
+ bool emit(const Module& pModule, int pFileDescriptor);
bool reset();
diff --git a/include/mcld/LinkerConfig.h b/include/mcld/LinkerConfig.h
index 96dd5dc..a41be39 100644
--- a/include/mcld/LinkerConfig.h
+++ b/include/mcld/LinkerConfig.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LINKER_CONFIG_H
-#define MCLD_LINKER_CONFIG_H
+#ifndef MCLD_LINKERCONFIG_H
+#define MCLD_LINKERCONFIG_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/LinkerScript.h b/include/mcld/LinkerScript.h
index 91e4bdb..bdd0917 100644
--- a/include/mcld/LinkerScript.h
+++ b/include/mcld/LinkerScript.h
@@ -6,21 +6,26 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LINKER_SCRIPT_H
-#define MCLD_LINKER_SCRIPT_H
+#ifndef MCLD_LINKERSCRIPT_H
+#define MCLD_LINKERSCRIPT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <string>
+#include <vector>
#include <llvm/ADT/StringRef.h>
#include <mcld/ADT/StringEntry.h>
#include <mcld/ADT/StringHash.h>
#include <mcld/ADT/HashTable.h>
#include <mcld/Object/SectionMap.h>
#include <mcld/MC/SearchDirs.h>
+#include <mcld/Script/Assignment.h>
+#include <mcld/Script/AssertCmd.h>
namespace mcld {
+class LDSymbol;
+
/** \class LinkerScript
*
*/
@@ -28,16 +33,16 @@
{
public:
typedef HashTable<StringEntry<llvm::StringRef>,
- hash::StringHash<hash::ELF>,
+ hash::StringHash<hash::DJB>,
StringEntryFactory<llvm::StringRef> > SymbolRenameMap;
typedef HashTable<StringEntry<uint64_t>,
- hash::StringHash<hash::ELF>,
+ hash::StringHash<hash::DJB>,
StringEntryFactory<uint64_t> > AddressMap;
- typedef HashTable<StringEntry<llvm::StringRef>,
- hash::StringHash<hash::ELF>,
- StringEntryFactory<llvm::StringRef> > DefSymMap;
+ typedef std::vector<std::pair<LDSymbol*, Assignment> > Assignments;
+
+ typedef std::vector<AssertCmd> Assertions;
public:
LinkerScript();
@@ -53,8 +58,11 @@
const SectionMap& sectionMap() const { return m_SectionMap; }
SectionMap& sectionMap() { return m_SectionMap; }
- const DefSymMap& defSymMap() const { return m_DefSymMap; }
- DefSymMap& defSymMap() { return m_DefSymMap; }
+ const Assignments& assignments() const { return m_Assignments; }
+ Assignments& assignments() { return m_Assignments; }
+
+ const Assertions& assertions() const { return m_Assertions; }
+ Assertions& assertions() { return m_Assertions; }
/// search directory
const SearchDirs& directories() const { return m_SearchDirs; }
@@ -67,12 +75,29 @@
bool hasSysroot() const;
+ /// entry point
+ const std::string& entry() const;
+
+ void setEntry(const std::string& pEntry);
+
+ bool hasEntry() const;
+
+ /// output filename
+ const std::string& outputFile() const;
+
+ void setOutputFile(const std::string& pOutputFile);
+
+ bool hasOutputFile() const;
+
private:
SymbolRenameMap m_SymbolRenames;
AddressMap m_AddressMap;
SectionMap m_SectionMap;
- DefSymMap m_DefSymMap;
+ Assignments m_Assignments;
+ Assertions m_Assertions;
SearchDirs m_SearchDirs;
+ std::string m_Entry;
+ std::string m_OutputFile;
};
} // namespace of mcld
diff --git a/include/mcld/MC/Attribute.h b/include/mcld/MC/Attribute.h
index 11f6d26..a7c7176 100644
--- a/include/mcld/MC/Attribute.h
+++ b/include/mcld/MC/Attribute.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ATTRIBUTE_H
-#define MCLD_ATTRIBUTE_H
+#ifndef MCLD_MC_ATTRIBUTE_H
+#define MCLD_MC_ATTRIBUTE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/MC/AttributeSet.h b/include/mcld/MC/AttributeSet.h
index e50384d..97b20a9 100644
--- a/include/mcld/MC/AttributeSet.h
+++ b/include/mcld/MC/AttributeSet.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ATTRIBUTE_SET_H
-#define MCLD_ATTRIBUTE_SET_H
+#ifndef MCLD_MC_ATTRIBUTESET_H
+#define MCLD_MC_ATTRIBUTESET_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/MC/CommandAction.h b/include/mcld/MC/CommandAction.h
index a0ff909..19f74fd 100644
--- a/include/mcld/MC/CommandAction.h
+++ b/include/mcld/MC/CommandAction.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_MC_COMMAND_ACTION_H
-#define MCLD_MC_COMMAND_ACTION_H
+#ifndef MCLD_MC_COMMANDACTION_H
+#define MCLD_MC_COMMANDACTION_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -15,11 +15,13 @@
#include <string>
#include <mcld/Support/Path.h>
#include <mcld/MC/InputAction.h>
+#include <mcld/Script/ScriptFile.h>
namespace mcld {
class SearchDirs;
class InputBuilder;
+class LinkerConfig;
//===----------------------------------------------------------------------===//
// Derived InputAction
@@ -44,7 +46,7 @@
public:
NamespecAction(unsigned int pPosition,
const std::string &pNamespec,
- SearchDirs& pSearchDirs);
+ const SearchDirs& pSearchDirs);
const std::string &namespec() const { return m_Namespec; }
@@ -52,7 +54,7 @@
private:
std::string m_Namespec;
- SearchDirs& m_SearchDirs;
+ const SearchDirs& m_SearchDirs;
};
/// BitcodeAction
@@ -159,6 +161,41 @@
bool activate(InputBuilder&) const;
};
+/// DefSymAction
+class DefSymAction : public InputAction
+{
+public:
+ explicit DefSymAction(unsigned int pPosition, std::string& pAssignment);
+
+ bool activate(InputBuilder&) const;
+
+ const std::string& assignment() const { return m_Assignment; }
+
+private:
+ std::string& m_Assignment;
+};
+
+/// ScriptAction
+class ScriptAction : public InputAction
+{
+public:
+ ScriptAction(unsigned int pPosition,
+ const std::string& pFileName,
+ ScriptFile::Kind pKind,
+ const SearchDirs& pSearchDirs);
+
+ bool activate(InputBuilder&) const;
+
+ const std::string& filename() const { return m_FileName; }
+
+ ScriptFile::Kind kind() const { return m_Kind; }
+
+private:
+ std::string m_FileName;
+ ScriptFile::Kind m_Kind;
+ const SearchDirs& m_SearchDirs;
+};
+
} // end of namespace mcld
#endif
diff --git a/include/mcld/MC/ContextFactory.h b/include/mcld/MC/ContextFactory.h
index dde2627..169dbfa 100644
--- a/include/mcld/MC/ContextFactory.h
+++ b/include/mcld/MC/ContextFactory.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_CONTEXT_FACTORY_H
-#define MCLD_CONTEXT_FACTORY_H
+#ifndef MCLD_MC_CONTEXTFACTORY_H
+#define MCLD_MC_CONTEXTFACTORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/MC/FileAction.h b/include/mcld/MC/FileAction.h
index 4644405..269c700 100644
--- a/include/mcld/MC/FileAction.h
+++ b/include/mcld/MC/FileAction.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_MC_FILE_ACTION_H
-#define MCLD_MC_FILE_ACTION_H
+#ifndef MCLD_MC_FILEACTION_H
+#define MCLD_MC_FILEACTION_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -17,7 +17,6 @@
namespace mcld {
class ContextFactory;
-class MemoryAreaFactory;
/** \class ContextAction
* \brief ContextAction is a command object to create input's LDContext.
diff --git a/include/mcld/MC/MCLDInput.h b/include/mcld/MC/Input.h
similarity index 95%
rename from include/mcld/MC/MCLDInput.h
rename to include/mcld/MC/Input.h
index 94b9479..a8e9c35 100644
--- a/include/mcld/MC/MCLDInput.h
+++ b/include/mcld/MC/Input.h
@@ -1,4 +1,4 @@
-//===- MCLDInput.h --------------------------------------------------------===//
+//===- Input.h ------------------------------------------------------------===//
//
// The MCLinker Project
//
@@ -10,8 +10,8 @@
// Input class inherits MCLDFile, which is used to represent a input file
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_INPUT_H
-#define MCLD_INPUT_H
+#ifndef MCLD_MC_INPUT_H
+#define MCLD_MC_INPUT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -35,6 +35,7 @@
public:
enum Type {
Unknown,
+ Binary,
Object,
Exec,
DynObj,
diff --git a/include/mcld/MC/InputAction.h b/include/mcld/MC/InputAction.h
index fb7d660..4b94378 100644
--- a/include/mcld/MC/InputAction.h
+++ b/include/mcld/MC/InputAction.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_MC_INPUT_ACTION_H
-#define MCLD_MC_INPUT_ACTION_H
+#ifndef MCLD_MC_INPUTACTION_H
+#define MCLD_MC_INPUTACTION_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/MC/InputBuilder.h b/include/mcld/MC/InputBuilder.h
index 0301c15..1b2e8b9 100644
--- a/include/mcld/MC/InputBuilder.h
+++ b/include/mcld/MC/InputBuilder.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_MC_INPUT_BUILDER_H
-#define MCLD_MC_INPUT_BUILDER_H
+#ifndef MCLD_MC_INPUTBUILDER_H
+#define MCLD_MC_INPUTBUILDER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -16,7 +16,7 @@
#include <stack>
#include <mcld/InputTree.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
#include <mcld/Support/FileHandle.h>
namespace mcld {
@@ -26,7 +26,6 @@
class ContextFactory;
class MemoryAreaFactory;
class AttrConstraint;
-class raw_mem_ostream;
/** \class InputBuilder
* \brief InputBuilder recieves InputActions and build the InputTree.
diff --git a/include/mcld/MC/InputFactory.h b/include/mcld/MC/InputFactory.h
index d644222..8c73d0b 100644
--- a/include/mcld/MC/InputFactory.h
+++ b/include/mcld/MC/InputFactory.h
@@ -6,13 +6,13 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_INPUT_FACTORY_H
-#define MCLD_INPUT_FACTORY_H
+#ifndef MCLD_MC_INPUTFACTORY_H
+#define MCLD_MC_INPUTFACTORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <mcld/Support/GCFactory.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
namespace mcld {
diff --git a/include/mcld/MC/MCLDDirectory.h b/include/mcld/MC/MCLDDirectory.h
index 988f9d3..77692c0 100644
--- a/include/mcld/MC/MCLDDirectory.h
+++ b/include/mcld/MC/MCLDDirectory.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_MCLDDIRECTORY_H
-#define MCLD_MCLDDIRECTORY_H
+#ifndef MCLD_MC_MCLDDIRECTORY_H
+#define MCLD_MC_MCLDDIRECTORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/MC/SearchDirs.h b/include/mcld/MC/SearchDirs.h
index 0c0c657..a3bcf39 100644
--- a/include/mcld/MC/SearchDirs.h
+++ b/include/mcld/MC/SearchDirs.h
@@ -12,7 +12,7 @@
#include <gtest.h>
#endif
#include <mcld/ADT/Uncopyable.h>
-#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Input.h>
#include <mcld/Support/Path.h>
#include <llvm/ADT/StringRef.h>
diff --git a/include/mcld/MC/SymbolCategory.h b/include/mcld/MC/SymbolCategory.h
index 61c015e..9ecc5b9 100644
--- a/include/mcld/MC/SymbolCategory.h
+++ b/include/mcld/MC/SymbolCategory.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_SYMBOL_CATEGORY_H
-#define MCLD_SYMBOL_CATEGORY_H
+#ifndef MCLD_MC_SYMBOLCATEGORY_H
+#define MCLD_MC_SYMBOLCATEGORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/MC/ZOption.h b/include/mcld/MC/ZOption.h
index e451734..d9cd635 100644
--- a/include/mcld/MC/ZOption.h
+++ b/include/mcld/MC/ZOption.h
@@ -6,15 +6,15 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ZOPTION_H
-#define MCLD_ZOPTION_H
+#ifndef MCLD_MC_ZOPTION_H
+#define MCLD_MC_ZOPTION_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
+
#include <llvm/Support/DataTypes.h>
-namespace mcld
-{
+namespace mcld {
/** \class ZOption
* \brief The -z options for GNU ld compatibility.
@@ -50,19 +50,13 @@
public:
ZOption();
- ~ZOption();
+ Kind kind() const { return m_Kind; }
- Kind kind() const
- { return m_Kind; }
+ void setKind(Kind pKind) { m_Kind = pKind; }
- uint64_t pageSize() const
- { return m_PageSize; }
+ uint64_t pageSize() const { return m_PageSize; }
- void setKind(Kind pKind)
- { m_Kind = pKind; }
-
- void setPageSize(uint64_t pPageSize)
- { m_PageSize = pPageSize; }
+ void setPageSize(uint64_t pPageSize) { m_PageSize = pPageSize; }
private:
Kind m_Kind;
diff --git a/include/mcld/Module.h b/include/mcld/Module.h
index 9ea9812..9dfb59e 100644
--- a/include/mcld/Module.h
+++ b/include/mcld/Module.h
@@ -16,25 +16,18 @@
#include <gtest.h>
#endif
-#include <vector>
-#include <string>
-#include <map>
-
-#include <mcld/LinkerScript.h>
#include <mcld/InputTree.h>
-#include <mcld/ADT/HashTable.h>
-#include <mcld/ADT/HashEntry.h>
-#include <mcld/Support/GCFactoryListTraits.h>
-#include <mcld/Fragment/Fragment.h>
#include <mcld/LD/NamePool.h>
#include <mcld/LD/SectionSymbolSet.h>
#include <mcld/MC/SymbolCategory.h>
-#include <mcld/MC/MCLDInput.h>
-#include <llvm/ADT/ilist.h>
+#include <vector>
+#include <string>
namespace mcld {
+class Input;
+class LinkerScript;
class LDSection;
class LDSymbol;
diff --git a/include/mcld/Object/ObjectBuilder.h b/include/mcld/Object/ObjectBuilder.h
index 79f81a5..ec80528 100644
--- a/include/mcld/Object/ObjectBuilder.h
+++ b/include/mcld/Object/ObjectBuilder.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_OBJECT_OBJECT_BUILDER_H
-#define MCLD_OBJECT_OBJECT_BUILDER_H
+#ifndef MCLD_OBJECT_OBJECTBUILDER_H
+#define MCLD_OBJECT_OBJECTBUILDER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -27,6 +27,7 @@
class RelocData;
class Fragment;
class Relocation;
+class Input;
/** \class ObjectBuilder
* \brief ObjectBuilder recieve ObjectAction and build the mcld::Module.
@@ -67,7 +68,7 @@
/// @param [in] pInputSection The merged input section.
/// @return The merged output section. If the corresponding output sections
/// is not defined, return NULL.
- LDSection* MergeSection(LDSection& pInputSection);
+ LDSection* MergeSection(const Input& pInputFile, LDSection& pInputSection);
/// MoveSectionData - move the fragment of pFrom to pTo section data.
static bool MoveSectionData(SectionData& pFrom, SectionData& pTo);
diff --git a/include/mcld/Object/ObjectLinker.h b/include/mcld/Object/ObjectLinker.h
index 128cf64..5c8c5cc 100644
--- a/include/mcld/Object/ObjectLinker.h
+++ b/include/mcld/Object/ObjectLinker.h
@@ -6,39 +6,34 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// ObjectLinker plays the same role as GNU collect2 to prepare all implicit
-// parameters for FragmentLinker.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_OBJECT_OBJECT_LINKER_H
-#define MCLD_OBJECT_OBJECT_LINKER_H
+#ifndef MCLD_OBJECT_OBJECTLINKER_H
+#define MCLD_OBJECT_OBJECTLINKER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <stddef.h>
+#include <llvm/Support/DataTypes.h>
namespace mcld {
class Module;
class LinkerConfig;
class IRBuilder;
-class FragmentLinker;
class TargetLDBackend;
-class MemoryArea;
-class MemoryAreaFactory;
+class FileOutputBuffer;
class ObjectReader;
class DynObjReader;
class ArchiveReader;
class GroupReader;
class BinaryReader;
+class ScriptReader;
class ObjectWriter;
class DynObjWriter;
class ExecWriter;
class BinaryWriter;
+class Relocation;
+class ResolveInfo;
/** \class ObjectLinker
- * \brief ObjectLinker prepares parameters for FragmentLinker.
*/
class ObjectLinker
{
@@ -48,11 +43,7 @@
~ObjectLinker();
- void setup(Module& pModule, IRBuilder& pBuilder);
-
- /// initFragmentLinker - initialize FragmentLinker
- /// Connect all components in FragmentLinker
- bool initFragmentLinker();
+ bool initialize(Module& pModule, IRBuilder& pBuilder);
/// initStdSections - initialize standard sections of the output file.
bool initStdSections();
@@ -69,9 +60,16 @@
/// readRelocations - read all relocation entries
bool readRelocations();
+ /// dataStrippingOpt - optimizations for reducing code size
+ void dataStrippingOpt();
+
/// mergeSections - put allinput sections into output sections
bool mergeSections();
+ /// addSymbolsToOutput - after all symbols has been resolved, add the symbol
+ /// to output
+ void addSymbolsToOutput(Module& pModule);
+
/// allocateCommonSymobols - allocate fragments for common symbols to the
/// corresponding sections
bool allocateCommonSymbols();
@@ -122,18 +120,10 @@
bool finalizeSymbolValue();
/// emitOutput - emit the output file.
- bool emitOutput(MemoryArea& pOutput);
+ bool emitOutput(FileOutputBuffer& pOutput);
/// postProcessing - do modificatiion after all processes
- bool postProcessing(MemoryArea& pOutput);
-
- /// getLinker - get internal FragmentLinker object
- const FragmentLinker* getLinker() const { return m_pLinker; }
- FragmentLinker* getLinker() { return m_pLinker; }
-
- /// hasInitLinker - has Linker been initialized?
- bool hasInitLinker() const
- { return (NULL != m_pLinker); }
+ bool postProcessing(FileOutputBuffer& pOutput);
// ----- readers and writers ----- //
const ObjectReader* getObjectReader () const { return m_pObjectReader; }
@@ -151,12 +141,31 @@
const BinaryReader* getBinaryReader () const { return m_pBinaryReader; }
BinaryReader* getBinaryReader () { return m_pBinaryReader; }
+ const ScriptReader* getScriptReader () const { return m_pScriptReader; }
+ ScriptReader* getScriptReader () { return m_pScriptReader; }
+
const ObjectWriter* getWriter () const { return m_pWriter; }
ObjectWriter* getWriter () { return m_pWriter; }
private:
+ /// normalSyncRelocationResult - sync relocation result when producing shared
+ /// objects or executables
+ void normalSyncRelocationResult(FileOutputBuffer& pOutput);
+
+ /// partialSyncRelocationResult - sync relocation result when doing partial
+ /// link
+ void partialSyncRelocationResult(FileOutputBuffer& pOutput);
+
+ /// writeRelocationResult - helper function of syncRelocationResult, write
+ /// relocation target data to output
+ void writeRelocationResult(Relocation& pReloc, uint8_t* pOutput);
+
+ /// addSymbolToOutput - add a symbol to output symbol table if it's not a
+ /// section symbol and not defined in the discarded section
+ void addSymbolToOutput(ResolveInfo& pInfo, Module& pModule);
+
+private:
const LinkerConfig& m_Config;
- FragmentLinker* m_pLinker;
Module* m_pModule;
IRBuilder* m_pBuilder;
@@ -168,6 +177,7 @@
ArchiveReader* m_pArchiveReader;
GroupReader* m_pGroupReader;
BinaryReader* m_pBinaryReader;
+ ScriptReader* m_pScriptReader;
ObjectWriter* m_pWriter;
};
diff --git a/include/mcld/Object/SectionMap.h b/include/mcld/Object/SectionMap.h
index 37df4a3..e6e779d 100644
--- a/include/mcld/Object/SectionMap.h
+++ b/include/mcld/Object/SectionMap.h
@@ -6,82 +6,206 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_SECTION_MAP_H
-#define MCLD_SECTION_MAP_H
+#ifndef MCLD_OBJECT_SECTIONMAP_H
+#define MCLD_OBJECT_SECTIONMAP_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
+#include <mcld/Script/OutputSectDesc.h>
+#include <mcld/Script/InputSectDesc.h>
+#include <mcld/Script/Assignment.h>
+#include <llvm/Support/DataTypes.h>
#include <vector>
#include <string>
-#include <llvm/Support/DataTypes.h>
-
namespace mcld {
+class Fragment;
+class LDSection;
+
/** \class SectionMap
- * \brief descirbe the mappings of input section's name (or prefix) to
- * its associated output section's name and offset
+ * \brief descirbe how to map input sections into output sections
*/
class SectionMap
{
public:
- // a mapping in SectionMap is the triple of
- // {input substr, output section's name, output section's offset}
- struct NamePair
- {
+ class Input {
public:
- NamePair();
- NamePair(const std::string& pFrom, const std::string& pTo);
+ typedef std::vector<std::pair<Fragment*, Assignment> > DotAssignments;
+ typedef DotAssignments::const_iterator const_dot_iterator;
+ typedef DotAssignments::iterator dot_iterator;
- bool isNull() const;
+ Input(const std::string& pName, InputSectDesc::KeepPolicy pPolicy);
+ Input(const InputSectDesc& pInputDesc);
- public:
- unsigned int hash;
- std::string from;
- std::string to;
+ InputSectDesc::KeepPolicy policy() const { return m_Policy; }
+
+ const InputSectDesc::Spec& spec() const { return m_Spec; }
+
+ const LDSection* getSection() const { return m_pSection; }
+ LDSection* getSection() { return m_pSection; }
+
+ const_dot_iterator dot_begin() const { return m_DotAssignments.begin(); }
+ dot_iterator dot_begin() { return m_DotAssignments.begin(); }
+ const_dot_iterator dot_end () const { return m_DotAssignments.end(); }
+ dot_iterator dot_end () { return m_DotAssignments.end(); }
+
+ const DotAssignments& dotAssignments() const { return m_DotAssignments; }
+ DotAssignments& dotAssignments() { return m_DotAssignments; }
+
+ private:
+ InputSectDesc::KeepPolicy m_Policy;
+ InputSectDesc::Spec m_Spec;
+ LDSection* m_pSection;
+ DotAssignments m_DotAssignments;
};
- typedef std::vector<NamePair> NamePairList;
- typedef NamePairList::iterator iterator;
- typedef NamePairList::const_iterator const_iterator;
+ class Output {
+ public:
+ typedef std::vector<Input*> InputList;
+ typedef InputList::const_iterator const_iterator;
+ typedef InputList::iterator iterator;
+ typedef InputList::const_reference const_reference;
+ typedef InputList::reference reference;
- /// NullName - the null object of NamePair
- static NamePair NullName;
+ typedef std::vector<Assignment> DotAssignments;
+ typedef DotAssignments::const_iterator const_dot_iterator;
+ typedef DotAssignments::iterator dot_iterator;
+
+ Output(const std::string& pName);
+ Output(const OutputSectDesc& pOutputDesc);
+
+ const std::string& name() const { return m_Name; }
+
+ const OutputSectDesc::Prolog& prolog() const { return m_Prolog; }
+ OutputSectDesc::Prolog& prolog() { return m_Prolog; }
+
+ const OutputSectDesc::Epilog& epilog() const { return m_Epilog; }
+ OutputSectDesc::Epilog& epilog() { return m_Epilog; }
+
+ size_t order() const { return m_Order; }
+
+ void setOrder(size_t pOrder) { m_Order = pOrder; }
+
+ bool hasContent() const;
+
+ const LDSection* getSection() const { return m_pSection; }
+ LDSection* getSection() { return m_pSection; }
+
+ void setSection(LDSection* pSection) { m_pSection = pSection; }
+
+ const_iterator begin() const { return m_InputList.begin(); }
+ iterator begin() { return m_InputList.begin(); }
+ const_iterator end () const { return m_InputList.end(); }
+ iterator end () { return m_InputList.end(); }
+
+ const_reference front() const { return m_InputList.front(); }
+ reference front() { return m_InputList.front(); }
+ const_reference back () const { return m_InputList.back(); }
+ reference back () { return m_InputList.back(); }
+
+ size_t size() const { return m_InputList.size(); }
+
+ bool empty() const { return m_InputList.empty(); }
+
+ bool isDiscard() const { return m_bIsDiscard; }
+
+ void append(Input* pInput) { m_InputList.push_back(pInput); }
+
+ const_dot_iterator dot_begin() const { return m_DotAssignments.begin(); }
+ dot_iterator dot_begin() { return m_DotAssignments.begin(); }
+ const_dot_iterator dot_end () const { return m_DotAssignments.end(); }
+ dot_iterator dot_end () { return m_DotAssignments.end(); }
+
+ const_dot_iterator find_first_explicit_dot() const;
+ dot_iterator find_first_explicit_dot();
+
+ const_dot_iterator find_last_explicit_dot() const;
+ dot_iterator find_last_explicit_dot();
+
+ const DotAssignments& dotAssignments() const { return m_DotAssignments; }
+ DotAssignments& dotAssignments() { return m_DotAssignments; }
+
+ private:
+ std::string m_Name;
+ OutputSectDesc::Prolog m_Prolog;
+ OutputSectDesc::Epilog m_Epilog;
+ LDSection* m_pSection;
+ size_t m_Order;
+ bool m_bIsDiscard;
+ InputList m_InputList;
+ DotAssignments m_DotAssignments;
+ };
+
+ struct SHOCompare
+ {
+ bool operator()(const Output* LHS, const Output* RHS) const
+ { return LHS->order() < RHS->order(); }
+ };
+
+ typedef std::pair<const Output*, const Input*> const_mapping;
+ typedef std::pair<Output*, Input*> mapping;
+
+ typedef std::vector<Output*> OutputDescList;
+ typedef OutputDescList::const_iterator const_iterator;
+ typedef OutputDescList::iterator iterator;
+ typedef OutputDescList::const_reference const_reference;
+ typedef OutputDescList::reference reference;
+
+ typedef OutputDescList::const_reverse_iterator const_reverse_iterator;
+ typedef OutputDescList::reverse_iterator reverse_iterator;
public:
- // get the possible output section name based on the mapping table
- // return NullPair if not found
- const NamePair& find(const std::string& pFrom) const;
- NamePair& find(const std::string& pFrom);
+ ~SectionMap();
- const NamePair& find(const std::string& pFrom, unsigned int pHash) const;
- NamePair& find(const std::string& pFrom, unsigned int pHash);
+ const_mapping find(const std::string& pInputFile,
+ const std::string& pInputSection) const;
+ mapping find(const std::string& pInputFile,
+ const std::string& pInputSection);
- // add a mapping from input sub-string to output name.
- // @param [in] pFrom the given input sub-string
- // @param [in] pTo the mapped output string
- // @param [out] pExist does pFrom exist?
- NamePair& append(const std::string& pFrom,
- const std::string& pTo,
- bool& pExist);
+ const_iterator find(const std::string& pOutputSection) const;
+ iterator find(const std::string& pOutputSection);
- const_iterator begin() const { return m_NamePairList.begin(); }
- iterator begin() { return m_NamePairList.begin(); }
- const_iterator end () const { return m_NamePairList.end(); }
- iterator end () { return m_NamePairList.end(); }
+ std::pair<mapping, bool>
+ insert(const std::string& pInputSection,
+ const std::string& pOutputSection,
+ InputSectDesc::KeepPolicy pPolicy = InputSectDesc::NoKeep);
+ std::pair<mapping, bool>
+ insert(const InputSectDesc& pInputDesc, const OutputSectDesc& pOutputDesc);
- bool empty() const { return m_NamePairList.empty(); }
- size_t size () const { return m_NamePairList.size(); }
+ bool empty() const { return m_OutputDescList.empty(); }
+ size_t size () const { return m_OutputDescList.size(); }
- static unsigned int hash(const std::string& pString);
+ const_iterator begin() const { return m_OutputDescList.begin(); }
+ iterator begin() { return m_OutputDescList.begin(); }
+ const_iterator end () const { return m_OutputDescList.end(); }
+ iterator end () { return m_OutputDescList.end(); }
+
+ const_reference front() const { return m_OutputDescList.front(); }
+ reference front() { return m_OutputDescList.front(); }
+ const_reference back () const { return m_OutputDescList.back(); }
+ reference back () { return m_OutputDescList.back(); }
+
+ const_reverse_iterator rbegin() const { return m_OutputDescList.rbegin(); }
+ reverse_iterator rbegin() { return m_OutputDescList.rbegin(); }
+ const_reverse_iterator rend () const { return m_OutputDescList.rend(); }
+ reverse_iterator rend () { return m_OutputDescList.rend(); }
+
+ iterator insert(iterator pPosition, LDSection* pSection);
+
+ // fixupDotSymbols - ensure the dot assignments are valid
+ void fixupDotSymbols();
private:
- bool matched(const NamePair& pNamePair,
- const std::string& pInput,
- unsigned int pHash) const;
+ bool matched(const Input& pInput,
+ const std::string& pInputFile,
+ const std::string& pInputSection) const;
+
+ bool matched(const WildcardPattern& pPattern, const std::string& pName) const;
+
private:
- NamePairList m_NamePairList;
+ OutputDescList m_OutputDescList;
};
} // namespace of mcld
diff --git a/include/mcld/Script/AssertCmd.h b/include/mcld/Script/AssertCmd.h
new file mode 100644
index 0000000..1e57375
--- /dev/null
+++ b/include/mcld/Script/AssertCmd.h
@@ -0,0 +1,58 @@
+//===- AssertCmd.h --------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_ASSERTCMD_H
+#define MCLD_SCRIPT_ASSERTCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <string>
+
+namespace mcld
+{
+
+class RpnExpr;
+class Module;
+
+/** \class AssertCmd
+ * \brief This class defines the interfaces to assert command.
+ */
+
+class AssertCmd : public ScriptCommand
+{
+public:
+ AssertCmd(RpnExpr& pRpnExpr, const std::string& pMessage);
+
+ ~AssertCmd();
+
+ AssertCmd& operator=(const AssertCmd& pAssertCmd);
+
+ const RpnExpr& getRpnExpr() const { return m_RpnExpr; }
+ RpnExpr& getRpnExpr() { return m_RpnExpr; }
+
+ const std::string& message() const { return m_Message; }
+
+ void dump() const;
+
+ static bool classof(const ScriptCommand* pCmd)
+ {
+ return pCmd->getKind() == ScriptCommand::ASSERT;
+ }
+
+ void activate(Module& pModule);
+
+private:
+ RpnExpr& m_RpnExpr;
+ std::string m_Message;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Script/Assignment.h b/include/mcld/Script/Assignment.h
new file mode 100644
index 0000000..068735d
--- /dev/null
+++ b/include/mcld/Script/Assignment.h
@@ -0,0 +1,87 @@
+//===- Assignment.h -------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_ASSIGNMENT_H
+#define MCLD_SCRIPT_ASSIGNMENT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+
+namespace mcld
+{
+
+class Module;
+class RpnExpr;
+class SymOperand;
+class RpnEvaluator;
+
+/** \class Assignment
+ * \brief This class defines the interfaces to assignment command.
+ */
+
+class Assignment : public ScriptCommand
+{
+public:
+ enum Level {
+ OUTSIDE_SECTIONS, // outside SECTIONS command
+ OUTPUT_SECTION, // related to an output section
+ INPUT_SECTION // related to an input section
+ };
+
+ enum Type {
+ DEFAULT,
+ HIDDEN,
+ PROVIDE,
+ PROVIDE_HIDDEN
+ };
+
+public:
+ Assignment(Level pLevel,
+ Type pType,
+ SymOperand& pSymbol,
+ RpnExpr& pRpnExpr);
+
+ ~Assignment();
+
+ Assignment& operator=(const Assignment& pAssignment);
+
+ Level level() const { return m_Level; }
+
+ Type type() const { return m_Type; }
+
+ const SymOperand& symbol() const { return m_Symbol; }
+ SymOperand& symbol() { return m_Symbol; }
+
+ const RpnExpr& getRpnExpr() const { return m_RpnExpr; }
+ RpnExpr& getRpnExpr() { return m_RpnExpr; }
+
+ void dump() const;
+
+ static bool classof(const ScriptCommand* pCmd)
+ {
+ return pCmd->getKind() == ScriptCommand::ASSIGNMENT;
+ }
+
+ void activate(Module& pModule);
+
+ /// assign - evaluate the rhs and assign the result to lhs.
+ bool assign(RpnEvaluator& pEvaluator);
+
+private:
+ Level m_Level;
+ Type m_Type;
+ SymOperand& m_Symbol;
+ RpnExpr& m_RpnExpr;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/BinaryOp.h b/include/mcld/Script/BinaryOp.h
new file mode 100644
index 0000000..884c0c1
--- /dev/null
+++ b/include/mcld/Script/BinaryOp.h
@@ -0,0 +1,135 @@
+//===- BinaryOp.h ---------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_BINARYOP_H
+#define MCLD_SCRIPT_BINARYOP_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/Operator.h>
+#include <cstddef>
+
+namespace mcld
+{
+
+class Operand;
+class IntOperand;
+class Module;
+class TargetLDBackend;
+
+/** \class BinaryOP
+ * \brief This class defines the interfaces to an binary operator token.
+ */
+
+template<Operator::Type TYPE>
+class BinaryOp : public Operator
+{
+private:
+ friend class Operator;
+
+ BinaryOp()
+ : Operator(Operator::BINARY, TYPE), m_Size(0)
+ {
+ m_pOperand[0] = m_pOperand[1] = NULL;
+ }
+
+public:
+ ~BinaryOp()
+ {}
+
+ IntOperand* eval(const Module& pModule, const TargetLDBackend& pBackend);
+
+ void appendOperand(Operand* pOperand)
+ {
+ m_pOperand[m_Size++] = pOperand;
+ if (m_Size == 2)
+ m_Size = 0;
+ }
+
+private:
+ size_t m_Size;
+ Operand* m_pOperand[2];
+};
+
+template<>
+IntOperand* BinaryOp<Operator::MUL>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::DIV>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::MOD>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::ADD>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::SUB>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::LSHIFT>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::RSHIFT>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::LT>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::LE>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::GT>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::GE>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::EQ>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::NE>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::BITWISE_AND>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::BITWISE_XOR>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::BITWISE_OR>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::LOGICAL_AND>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::LOGICAL_OR>::eval(const Module&,
+ const TargetLDBackend&);
+
+template<>
+IntOperand* BinaryOp<Operator::ALIGN>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand*
+BinaryOp<Operator::DATA_SEGMENT_RELRO_END>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::MAX>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::MIN>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* BinaryOp<Operator::SEGMENT_START>::eval(const Module&,
+ const TargetLDBackend&);
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/EntryCmd.h b/include/mcld/Script/EntryCmd.h
new file mode 100644
index 0000000..acbdd10
--- /dev/null
+++ b/include/mcld/Script/EntryCmd.h
@@ -0,0 +1,49 @@
+//===- EntryCmd.h ---------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_ENTRYCMD_H
+#define MCLD_SCRIPT_ENTRYCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <string>
+
+namespace mcld
+{
+
+class Module;
+
+/** \class EntryCmd
+ * \brief This class defines the interfaces to Entry command.
+ */
+
+class EntryCmd : public ScriptCommand
+{
+public:
+ EntryCmd(const std::string& pEntry);
+ ~EntryCmd();
+
+ void dump() const;
+
+ static bool classof(const ScriptCommand* pCmd)
+ {
+ return pCmd->getKind() == ScriptCommand::ENTRY;
+ }
+
+ void activate(Module& pModule);
+
+private:
+ std::string m_Entry;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/ExprToken.h b/include/mcld/Script/ExprToken.h
new file mode 100644
index 0000000..be248d5
--- /dev/null
+++ b/include/mcld/Script/ExprToken.h
@@ -0,0 +1,50 @@
+//===- ExprToken.h --------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_EXPRTOKEN_H
+#define MCLD_SCRIPT_EXPRTOKEN_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+namespace mcld
+{
+
+/** \class ExprToken
+ * \brief This class defines the interfaces to an expression token.
+ */
+
+class ExprToken
+{
+public:
+ enum Kind {
+ OPERATOR,
+ OPERAND
+ };
+
+protected:
+ ExprToken(Kind pKind)
+ : m_Kind(pKind)
+ {}
+
+public:
+ virtual ~ExprToken()
+ {}
+
+ virtual void dump() const = 0;
+
+ Kind kind() const { return m_Kind; }
+
+private:
+ Kind m_Kind;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/FileToken.h b/include/mcld/Script/FileToken.h
new file mode 100644
index 0000000..92faab4
--- /dev/null
+++ b/include/mcld/Script/FileToken.h
@@ -0,0 +1,50 @@
+//===- FileToken.h --------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_FILETOKEN_H
+#define MCLD_SCRIPT_FILETOKEN_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/InputToken.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
+
+namespace mcld
+{
+
+/** \class FileToken
+ * \brief This class defines the interfaces to a filename in INPUT/GROUP
+ * command.
+ */
+
+class FileToken : public InputToken
+{
+private:
+ friend class Chunk<FileToken, MCLD_SYMBOLS_PER_INPUT>;
+ FileToken();
+ FileToken(const std::string& pName, bool pAsNeeded);
+
+public:
+ ~FileToken();
+
+ static bool classof(const InputToken* pToken)
+ {
+ return pToken->type() == InputToken::File;
+ }
+
+ /* factory method */
+ static FileToken* create(const std::string& pName, bool pAsNeeded);
+ static void destroy(FileToken*& pToken);
+ static void clear();
+};
+
+} // namepsace of mcld
+
+#endif
diff --git a/include/mcld/Script/FlexLexer.h b/include/mcld/Script/FlexLexer.h
new file mode 100644
index 0000000..f09ab20
--- /dev/null
+++ b/include/mcld/Script/FlexLexer.h
@@ -0,0 +1,215 @@
+//===- FlexLexer.h --------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// -*-C++-*-
+// FlexLexer.h -- define interfaces for lexical analyzer classes generated
+// by flex
+
+// Copyright (c) 1993 The Regents of the University of California.
+// All rights reserved.
+//
+// This code is derived from software contributed to Berkeley by
+// Kent Williams and Tom Epperly.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+
+// Neither the name of the University nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+
+// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE.
+
+// This file defines FlexLexer, an abstract class which specifies the
+// external interface provided to flex C++ lexer objects, and yyFlexLexer,
+// which defines a particular lexer class.
+//
+// If you want to create multiple lexer classes, you use the -P flag
+// to rename each yyFlexLexer to some other xxFlexLexer. You then
+// include <FlexLexer.h> in your other sources once per lexer class:
+//
+// #undef yyFlexLexer
+// #define yyFlexLexer xxFlexLexer
+// #include <FlexLexer.h>
+//
+// #undef yyFlexLexer
+// #define yyFlexLexer zzFlexLexer
+// #include <FlexLexer.h>
+// ...
+
+#ifndef __FLEX_LEXER_H
+// Never included before - need to define base class.
+#define __FLEX_LEXER_H
+
+#include <iostream>
+# ifndef FLEX_STD
+# define FLEX_STD std::
+# endif
+
+extern "C++" {
+
+struct yy_buffer_state;
+typedef int yy_state_type;
+
+class FlexLexer {
+public:
+ virtual ~FlexLexer() { }
+
+ const char* YYText() const { return yytext; }
+ int YYLeng() const { return yyleng; }
+
+ virtual void
+ yy_switch_to_buffer( struct yy_buffer_state* new_buffer ) = 0;
+ virtual struct yy_buffer_state*
+ yy_create_buffer( FLEX_STD istream* s, int size ) = 0;
+ virtual void yy_delete_buffer( struct yy_buffer_state* b ) = 0;
+ virtual void yyrestart( FLEX_STD istream* s ) = 0;
+
+ virtual int yylex() = 0;
+
+ // Call yylex with new input/output sources.
+ int yylex( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 )
+ {
+ switch_streams( new_in, new_out );
+ return yylex();
+ }
+
+ // Switch to new input/output streams. A nil stream pointer
+ // indicates "keep the current one".
+ virtual void switch_streams( FLEX_STD istream* new_in = 0,
+ FLEX_STD ostream* new_out = 0 ) = 0;
+
+ int lineno() const { return yylineno; }
+
+ int debug() const { return yy_flex_debug; }
+ void set_debug( int flag ) { yy_flex_debug = flag; }
+
+protected:
+ char* yytext;
+ int yyleng;
+ int yylineno; // only maintained if you use %option yylineno
+ int yy_flex_debug; // only has effect with -d or "%option debug"
+};
+
+}
+#endif // FLEXLEXER_H
+
+#if defined(yyFlexLexer) || ! defined(yyFlexLexerOnce)
+// Either this is the first time through (yyFlexLexerOnce not defined),
+// or this is a repeated include to define a different flavor of
+// yyFlexLexer, as discussed in the flex manual.
+#define yyFlexLexerOnce
+
+extern "C++" {
+
+class yyFlexLexer : public FlexLexer {
+public:
+ // arg_yyin and arg_yyout default to the cin and cout, but we
+ // only make that assignment when initializing in yylex().
+ yyFlexLexer( FLEX_STD istream* arg_yyin = 0, FLEX_STD ostream* arg_yyout = 0 );
+
+ virtual ~yyFlexLexer();
+
+ void yy_switch_to_buffer( struct yy_buffer_state* new_buffer );
+ struct yy_buffer_state* yy_create_buffer( FLEX_STD istream* s, int size );
+ void yy_delete_buffer( struct yy_buffer_state* b );
+ void yyrestart( FLEX_STD istream* s );
+
+ void yypush_buffer_state( struct yy_buffer_state* new_buffer );
+ void yypop_buffer_state();
+
+ virtual int yylex();
+ virtual void switch_streams( FLEX_STD istream* new_in, FLEX_STD ostream* new_out = 0 );
+ virtual int yywrap();
+
+protected:
+ virtual int LexerInput( char* buf, int max_size );
+ virtual void LexerOutput( const char* buf, int size );
+ virtual void LexerError( const char* msg );
+
+ void yyunput( int c, char* buf_ptr );
+ int yyinput();
+
+ void yy_load_buffer_state();
+ void yy_init_buffer( struct yy_buffer_state* b, FLEX_STD istream* s );
+ void yy_flush_buffer( struct yy_buffer_state* b );
+
+ int yy_start_stack_ptr;
+ int yy_start_stack_depth;
+ int* yy_start_stack;
+
+ void yy_push_state( int new_state );
+ void yy_pop_state();
+ int yy_top_state();
+
+ yy_state_type yy_get_previous_state();
+ yy_state_type yy_try_NUL_trans( yy_state_type current_state );
+ int yy_get_next_buffer();
+
+ FLEX_STD istream* yyin; // input source for default LexerInput
+ FLEX_STD ostream* yyout; // output sink for default LexerOutput
+
+ // yy_hold_char holds the character lost when yytext is formed.
+ char yy_hold_char;
+
+ // Number of characters read into yy_ch_buf.
+ int yy_n_chars;
+
+ // Points to current character in buffer.
+ char* yy_c_buf_p;
+
+ int yy_init; // whether we need to initialize
+ int yy_start; // start state number
+
+ // Flag which is used to allow yywrap()'s to do buffer switches
+ // instead of setting up a fresh yyin. A bit of a hack ...
+ int yy_did_buffer_switch_on_eof;
+
+
+ size_t yy_buffer_stack_top; /**< index of top of stack. */
+ size_t yy_buffer_stack_max; /**< capacity of stack. */
+ struct yy_buffer_state ** yy_buffer_stack; /**< Stack as an array. */
+ void yyensure_buffer_stack(void);
+
+ // The following are not always needed, but may be depending
+ // on use of certain flex features (like REJECT or yymore()).
+
+ yy_state_type yy_last_accepting_state;
+ char* yy_last_accepting_cpos;
+
+ yy_state_type* yy_state_buf;
+ yy_state_type* yy_state_ptr;
+
+ char* yy_full_match;
+ int* yy_full_state;
+ int yy_full_lp;
+
+ int yy_lp;
+ int yy_looking_for_trail_begin;
+
+ int yy_more_flag;
+ int yy_more_len;
+ int yy_more_offset;
+ int yy_prev_more_offset;
+};
+
+}
+
+#endif // yyFlexLexer || ! yyFlexLexerOnce
+
diff --git a/include/mcld/Script/GroupCmd.h b/include/mcld/Script/GroupCmd.h
new file mode 100644
index 0000000..3006c79
--- /dev/null
+++ b/include/mcld/Script/GroupCmd.h
@@ -0,0 +1,60 @@
+//===- GroupCmd.h ---------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_GROUPCMD_H
+#define MCLD_SCRIPT_GROUPCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+
+namespace mcld
+{
+
+class StringList;
+class InputTree;
+class InputBuilder;
+class GroupReader;
+class LinkerConfig;
+
+/** \class GroupCmd
+ * \brief This class defines the interfaces to Group command.
+ */
+
+class GroupCmd : public ScriptCommand
+{
+public:
+ GroupCmd(StringList& pStringList,
+ InputTree& pInputTree,
+ InputBuilder& pBuilder,
+ GroupReader& m_GroupReader,
+ const LinkerConfig& pConfig);
+ ~GroupCmd();
+
+ void dump() const;
+
+ static bool classof(const ScriptCommand* pCmd)
+ {
+ return pCmd->getKind() == ScriptCommand::GROUP;
+ }
+
+ void activate(Module& pModule);
+
+private:
+ StringList& m_StringList;
+ InputTree& m_InputTree;
+ InputBuilder& m_Builder;
+ GroupReader& m_GroupReader;
+ const LinkerConfig& m_Config;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/InputSectDesc.h b/include/mcld/Script/InputSectDesc.h
new file mode 100644
index 0000000..e2bbf8d
--- /dev/null
+++ b/include/mcld/Script/InputSectDesc.h
@@ -0,0 +1,105 @@
+//===- InputSectDesc.h ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_INPUTSECTDESC_H
+#define MCLD_SCRIPT_INPUTSECTDESC_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <mcld/Script/StringList.h>
+#include <cassert>
+
+namespace mcld
+{
+
+class WildcardPattern;
+class OutputSectDesc;
+
+/** \class InputSectDesc
+ * \brief This class defines the interfaces to input section description.
+ */
+
+class InputSectDesc : public ScriptCommand
+{
+public:
+ enum KeepPolicy {
+ Keep,
+ NoKeep
+ };
+
+ struct Spec {
+ bool hasFile() const { return m_pWildcardFile != NULL; }
+ const WildcardPattern& file() const {
+ assert(hasFile());
+ return *m_pWildcardFile;
+ }
+
+ bool hasExcludeFiles() const {
+ return m_pExcludeFiles != NULL && !m_pExcludeFiles->empty();
+ }
+ const StringList& excludeFiles() const {
+ assert(hasExcludeFiles());
+ return *m_pExcludeFiles;
+ }
+
+ bool hasSections() const {
+ return m_pWildcardSections != NULL && !m_pWildcardSections->empty();
+ }
+ const StringList& sections() const {
+ assert(hasSections());
+ return *m_pWildcardSections;
+ }
+
+ bool operator==(const Spec& pRHS) const {
+ /* FIXME: currently I don't check the real content */
+ if (this == &pRHS)
+ return true;
+ if (m_pWildcardFile != pRHS.m_pWildcardFile)
+ return false;
+ if (m_pExcludeFiles != pRHS.m_pExcludeFiles)
+ return false;
+ if (m_pWildcardSections != pRHS.m_pWildcardSections)
+ return false;
+ return true;
+ }
+
+ WildcardPattern* m_pWildcardFile;
+ StringList* m_pExcludeFiles;
+ StringList* m_pWildcardSections;
+ };
+
+public:
+ InputSectDesc(KeepPolicy pPolicy,
+ const Spec& pSpec,
+ const OutputSectDesc& pOutputDesc);
+ ~InputSectDesc();
+
+ KeepPolicy policy() const { return m_KeepPolicy; }
+
+ const Spec& spec() const { return m_Spec; }
+
+ void dump() const;
+
+ static bool classof(const ScriptCommand* pCmd)
+ {
+ return pCmd->getKind() == ScriptCommand::INPUT_SECT_DESC;
+ }
+
+ void activate(Module& pModule);
+
+private:
+ KeepPolicy m_KeepPolicy;
+ Spec m_Spec;
+ const OutputSectDesc& m_OutputSectDesc;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Script/InputToken.h b/include/mcld/Script/InputToken.h
new file mode 100644
index 0000000..8d89022
--- /dev/null
+++ b/include/mcld/Script/InputToken.h
@@ -0,0 +1,56 @@
+//===- InputToken.h -------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_INPUTTOKEN_H
+#define MCLD_SCRIPT_INPUTTOKEN_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/StrToken.h>
+
+namespace mcld
+{
+
+/** \class InputToken
+ * \brief This class defines the interfaces to a file/namespec token.
+ */
+
+class InputToken : public StrToken
+{
+public:
+ enum Type {
+ Unknown,
+ File,
+ NameSpec
+ };
+
+protected:
+ InputToken();
+ InputToken(Type pType, const std::string& pName, bool pAsNeeded);
+
+public:
+ virtual ~InputToken();
+
+ Type type() const { return m_Type; }
+
+ bool asNeeded() const { return m_bAsNeeded; }
+
+ static bool classof(const StrToken* pToken)
+ {
+ return pToken->kind() == StrToken::Input;
+ }
+
+private:
+ Type m_Type;
+ bool m_bAsNeeded;
+};
+
+} // namepsace of mcld
+
+#endif
diff --git a/include/mcld/Script/NameSpec.h b/include/mcld/Script/NameSpec.h
new file mode 100644
index 0000000..96cf95c
--- /dev/null
+++ b/include/mcld/Script/NameSpec.h
@@ -0,0 +1,50 @@
+//===- NameSpec.h ---------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_NAMESPEC_H
+#define MCLD_SCRIPT_NAMESPEC_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/InputToken.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
+
+namespace mcld
+{
+
+/** \class NameSpec
+ * \brief This class defines the interfaces to a namespec in INPUT/GROUP
+ * command.
+ */
+
+class NameSpec : public InputToken
+{
+private:
+ friend class Chunk<NameSpec, MCLD_SYMBOLS_PER_INPUT>;
+ NameSpec();
+ NameSpec(const std::string& pName, bool pAsNeeded);
+
+public:
+ ~NameSpec();
+
+ static bool classof(const InputToken* pToken)
+ {
+ return pToken->type() == InputToken::NameSpec;
+ }
+
+ /* factory method */
+ static NameSpec* create(const std::string& pName, bool pAsNeeded);
+ static void destroy(NameSpec*& pToken);
+ static void clear();
+};
+
+} // namepsace of mcld
+
+#endif
diff --git a/include/mcld/Script/NullaryOp.h b/include/mcld/Script/NullaryOp.h
new file mode 100644
index 0000000..95fdc18
--- /dev/null
+++ b/include/mcld/Script/NullaryOp.h
@@ -0,0 +1,65 @@
+//===- NullaryOp.h --------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_NULLOP_H
+#define MCLD_SCRIPT_NULLOP_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/Operator.h>
+#include <cassert>
+
+namespace mcld
+{
+
+class Operand;
+class IntOperand;
+class Module;
+class TargetLDBackend;
+
+/** \class NullaryOp
+ * \brief This class defines the interfaces to an nullary operator token.
+ */
+
+template<Operator::Type TYPE>
+class NullaryOp : public Operator
+{
+private:
+ friend class Operator;
+
+ NullaryOp()
+ : Operator(Operator::NULLARY, TYPE)
+ {}
+
+public:
+ ~NullaryOp()
+ {}
+
+ IntOperand* eval(const Module& pModule, const TargetLDBackend& pBackend);
+
+ void appendOperand(Operand* pOperand)
+ {
+ assert(0);
+ }
+};
+
+template<>
+IntOperand* NullaryOp<Operator::SIZEOF_HEADERS>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* NullaryOp<Operator::MAXPAGESIZE>::eval(const Module&,
+ const TargetLDBackend&);
+
+template<>
+IntOperand* NullaryOp<Operator::COMMONPAGESIZE>::eval(const Module&,
+ const TargetLDBackend&);
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Script/Operand.h b/include/mcld/Script/Operand.h
new file mode 100644
index 0000000..403701c
--- /dev/null
+++ b/include/mcld/Script/Operand.h
@@ -0,0 +1,241 @@
+//===- Operand.h ----------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OPERAND_H
+#define MCLD_SCRIPT_OPERAND_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ExprToken.h>
+#include <mcld/Object/SectionMap.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
+#include <llvm/Support/DataTypes.h>
+#include <string>
+#include <cassert>
+
+namespace mcld
+{
+
+/** \class Operand
+ * \brief This class defines the interfaces to an operand token.
+ */
+
+class Operand : public ExprToken
+{
+public:
+ enum Type {
+ SYMBOL,
+ INTEGER,
+ SECTION,
+ SECTION_DESC,
+ FRAGMENT
+ };
+
+protected:
+ Operand(Type pType);
+ virtual ~Operand();
+
+public:
+ Type type() const { return m_Type; }
+
+ virtual bool isDot() const { return false; }
+
+ virtual uint64_t value() const = 0;
+
+ static bool classof(const ExprToken* pToken)
+ {
+ return pToken->kind() == ExprToken::OPERAND;
+ }
+
+private:
+ Type m_Type;
+};
+
+/** \class SymOperand
+ * \brief This class defines the interfaces to a symbol operand.
+ */
+
+class SymOperand : public Operand
+{
+private:
+ friend class Chunk<SymOperand, MCLD_SYMBOLS_PER_INPUT>;
+ SymOperand();
+ SymOperand(const std::string& pName);
+
+public:
+ void dump() const;
+
+ const std::string& name() const { return m_Name; }
+
+ bool isDot() const;
+
+ uint64_t value() const { return m_Value; }
+
+ void setValue(uint64_t pValue) { m_Value = pValue; }
+
+ static bool classof(const Operand* pOperand)
+ {
+ return pOperand->type() == Operand::SYMBOL;
+ }
+
+ /* factory method */
+ static SymOperand* create(const std::string& pName);
+ static void destroy(SymOperand*& pOperand);
+ static void clear();
+
+private:
+ std::string m_Name;
+ uint64_t m_Value;
+};
+
+/** \class IntOperand
+ * \brief This class defines the interfaces to an integer operand.
+ */
+
+class IntOperand : public Operand
+{
+private:
+ friend class Chunk<IntOperand, MCLD_SYMBOLS_PER_INPUT>;
+ IntOperand();
+ IntOperand(uint64_t pValue);
+
+public:
+ void dump() const;
+
+ uint64_t value() const { return m_Value; }
+
+ void setValue(uint64_t pValue) { m_Value = pValue; }
+
+ static bool classof(const Operand* pOperand)
+ {
+ return pOperand->type() == Operand::INTEGER;
+ }
+
+ /* factory method */
+ static IntOperand* create(uint64_t pValue);
+ static void destroy(IntOperand*& pOperand);
+ static void clear();
+
+private:
+ uint64_t m_Value;
+};
+
+/** \class SectOperand
+ * \brief This class defines the interfaces to an section name operand.
+ */
+class LDSection;
+
+class SectOperand : public Operand
+{
+private:
+ friend class Chunk<SectOperand, MCLD_SECTIONS_PER_INPUT>;
+ SectOperand();
+ SectOperand(const std::string& pName);
+
+public:
+ void dump() const;
+
+ const std::string& name() const { return m_Name; }
+
+ uint64_t value() const
+ {
+ assert(0);
+ return 0;
+ }
+
+ static bool classof(const Operand* pOperand)
+ {
+ return pOperand->type() == Operand::SECTION;
+ }
+
+ /* factory method */
+ static SectOperand* create(const std::string& pName);
+ static void destroy(SectOperand*& pOperand);
+ static void clear();
+
+private:
+ std::string m_Name;
+};
+
+/** \class SectDescOperand
+ * \brief This class defines the interfaces to an section name operand.
+ */
+
+class SectDescOperand : public Operand
+{
+private:
+ friend class Chunk<SectDescOperand, MCLD_SECTIONS_PER_INPUT>;
+ SectDescOperand();
+ SectDescOperand(const SectionMap::Output* pOutputDesc);
+
+public:
+ void dump() const;
+
+ const SectionMap::Output* outputDesc() const { return m_pOutputDesc; }
+
+ uint64_t value() const
+ {
+ assert(0);
+ return 0;
+ }
+
+ static bool classof(const Operand* pOperand)
+ {
+ return pOperand->type() == Operand::SECTION_DESC;
+ }
+
+ /* factory method */
+ static SectDescOperand* create(const SectionMap::Output* pOutputDesc);
+ static void destroy(SectDescOperand*& pOperand);
+ static void clear();
+
+private:
+ const SectionMap::Output* m_pOutputDesc;
+};
+
+/** \class FragOperand
+ * \brief This class defines the interfaces to a fragment operand.
+ */
+
+class Fragment;
+
+class FragOperand : public Operand
+{
+private:
+ friend class Chunk<FragOperand, MCLD_SYMBOLS_PER_INPUT>;
+ FragOperand();
+ FragOperand(Fragment& pFragment);
+
+public:
+ void dump() const;
+
+ const Fragment* frag() const { return m_pFragment; }
+ Fragment* frag() { return m_pFragment; }
+
+ uint64_t value() const;
+
+ static bool classof(const Operand* pOperand)
+ {
+ return pOperand->type() == Operand::FRAGMENT;
+ }
+
+ /* factory method */
+ static FragOperand* create(Fragment& pFragment);
+ static void destroy(FragOperand*& pOperand);
+ static void clear();
+
+private:
+ Fragment* m_pFragment;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/Operator.h b/include/mcld/Script/Operator.h
new file mode 100644
index 0000000..1fe8118
--- /dev/null
+++ b/include/mcld/Script/Operator.h
@@ -0,0 +1,231 @@
+//===- Operator.h ---------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OPERATOR_INTERFACE_H
+#define MCLD_SCRIPT_OPERATOR_INTERFACE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ExprToken.h>
+#include <llvm/Support/DataTypes.h>
+
+namespace mcld
+{
+
+class Operand;
+class IntOperand;
+class Module;
+class TargetLDBackend;
+
+/** \class Operator
+ * \brief This class defines the interfaces to an operator token.
+ */
+
+class Operator : public ExprToken
+{
+public:
+ enum Arity {
+ NULLARY,
+ UNARY,
+ BINARY,
+ TERNARY
+ };
+
+ enum Type {
+ /* arithmetic operator */
+ UNARY_PLUS = 0,
+ UNARY_MINUS = 1,
+ LOGICAL_NOT = 2,
+ BITWISE_NOT = 3,
+ MUL = 4,
+ DIV = 5,
+ MOD = 6,
+ ADD = 7,
+ SUB = 8,
+ LSHIFT = 9,
+ RSHIFT = 10,
+ LT = 11,
+ LE = 12,
+ GT = 13,
+ GE = 14,
+ EQ = 15,
+ NE = 16,
+ BITWISE_AND = 17,
+ BITWISE_XOR = 18,
+ BITWISE_OR = 19,
+ LOGICAL_AND = 20,
+ LOGICAL_OR = 21,
+ TERNARY_IF = 22,
+ ASSIGN = 23,
+ ADD_ASSIGN = 24,
+ SUB_ASSIGN = 25,
+ MUL_ASSIGN = 26,
+ DIV_ASSIGN = 27,
+ AND_ASSIGN = 28,
+ OR_ASSIGN = 29,
+ LS_ASSIGN = 30,
+ RS_ASSIGN = 31,
+ /* function */
+ ABSOLUTE = 32,
+ ADDR = 33,
+ ALIGN = 34,
+ ALIGNOF = 35,
+ BLOCK = 36,
+ DATA_SEGMENT_ALIGN = 37,
+ DATA_SEGMENT_END = 38,
+ DATA_SEGMENT_RELRO_END = 39,
+ DEFINED = 40,
+ LENGTH = 41,
+ LOADADDR = 42,
+ MAX = 43,
+ MIN = 44,
+ NEXT = 45,
+ ORIGIN = 46,
+ SEGMENT_START = 47,
+ SIZEOF = 48,
+ SIZEOF_HEADERS = 49,
+ MAXPAGESIZE = 50,
+ COMMONPAGESIZE = 51
+ };
+
+ static const char* OpNames[];
+
+protected:
+ Operator(Arity pArity, Type pType);
+
+ const IntOperand* result() const { return m_pIntOperand; }
+ IntOperand* result() { return m_pIntOperand; }
+
+public:
+ virtual ~Operator();
+
+ Arity arity() const { return m_Arity; }
+
+ Type type() const { return m_Type; }
+
+ virtual void dump() const;
+
+ virtual IntOperand* eval(const Module& pModule,
+ const TargetLDBackend& pBackend) = 0;
+
+ virtual void appendOperand(Operand* pOperand) = 0;
+
+ static bool classof(const ExprToken* pToken)
+ {
+ return pToken->kind() == ExprToken::OPERATOR;
+ }
+
+ template<Operator::Type TYPE>
+ static Operator& create();
+
+private:
+ Arity m_Arity;
+ Type m_Type;
+ IntOperand* m_pIntOperand;
+};
+
+/* Nullary operator */
+template<>
+Operator& Operator::create<Operator::SIZEOF_HEADERS>();
+template<>
+Operator& Operator::create<Operator::MAXPAGESIZE>();
+template<>
+Operator& Operator::create<Operator::COMMONPAGESIZE>();
+
+/* Unary operator */
+template<>
+Operator& Operator::create<Operator::UNARY_PLUS>();
+template<>
+Operator& Operator::create<Operator::UNARY_MINUS>();
+template<>
+Operator& Operator::create<Operator::LOGICAL_NOT>();
+template<>
+Operator& Operator::create<Operator::BITWISE_NOT>();
+
+template<>
+Operator& Operator::create<Operator::ABSOLUTE>();
+template<>
+Operator& Operator::create<Operator::ADDR>();
+template<>
+Operator& Operator::create<Operator::ALIGNOF>();
+template<>
+Operator& Operator::create<Operator::DATA_SEGMENT_END>();
+template<>
+Operator& Operator::create<Operator::DEFINED>();
+template<>
+Operator& Operator::create<Operator::LENGTH>();
+template<>
+Operator& Operator::create<Operator::LOADADDR>();
+template<>
+Operator& Operator::create<Operator::NEXT>();
+template<>
+Operator& Operator::create<Operator::ORIGIN>();
+template<>
+Operator& Operator::create<Operator::SIZEOF>();
+
+/* Binary operator */
+template<>
+Operator& Operator::create<Operator::MUL>();
+template<>
+Operator& Operator::create<Operator::DIV>();
+template<>
+Operator& Operator::create<Operator::MOD>();
+template<>
+Operator& Operator::create<Operator::ADD>();
+template<>
+Operator& Operator::create<Operator::SUB>();
+template<>
+Operator& Operator::create<Operator::LSHIFT>();
+template<>
+Operator& Operator::create<Operator::RSHIFT>();
+template<>
+Operator& Operator::create<Operator::LT>();
+template<>
+Operator& Operator::create<Operator::LE>();
+template<>
+Operator& Operator::create<Operator::GT>();
+template<>
+Operator& Operator::create<Operator::GE>();
+template<>
+Operator& Operator::create<Operator::EQ>();
+template<>
+Operator& Operator::create<Operator::NE>();
+template<>
+Operator& Operator::create<Operator::BITWISE_AND>();
+template<>
+Operator& Operator::create<Operator::BITWISE_XOR>();
+template<>
+Operator& Operator::create<Operator::BITWISE_OR>();
+template<>
+Operator& Operator::create<Operator::LOGICAL_AND>();
+template<>
+Operator& Operator::create<Operator::LOGICAL_OR>();
+
+template<>
+Operator& Operator::create<Operator::ALIGN>();
+template<>
+Operator& Operator::create<Operator::DATA_SEGMENT_RELRO_END>();
+template<>
+Operator& Operator::create<Operator::MAX>();
+template<>
+Operator& Operator::create<Operator::MIN>();
+template<>
+Operator& Operator::create<Operator::SEGMENT_START>();
+
+/* Ternary operator */
+template<>
+Operator& Operator::create<Operator::TERNARY_IF>();
+
+template<>
+Operator&
+Operator::create<Operator::DATA_SEGMENT_ALIGN>();
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/OutputArchCmd.h b/include/mcld/Script/OutputArchCmd.h
new file mode 100644
index 0000000..51b75cc
--- /dev/null
+++ b/include/mcld/Script/OutputArchCmd.h
@@ -0,0 +1,49 @@
+//===- OutputArchCmd.h ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OUTPUTARCHCMD_H
+#define MCLD_SCRIPT_OUTPUTARCHCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <string>
+
+namespace mcld
+{
+
+class Module;
+
+/** \class OutputArchCmd
+ * \brief This class defines the interfaces to OutputArch command.
+ */
+
+class OutputArchCmd : public ScriptCommand
+{
+public:
+ OutputArchCmd(const std::string& pArch);
+ ~OutputArchCmd();
+
+ void dump() const;
+
+ static bool classof(const ScriptCommand* pCmd)
+ {
+ return pCmd->getKind() == ScriptCommand::OUTPUT_ARCH;
+ }
+
+ void activate(Module& pModule);
+
+private:
+ std::string m_Arch;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/OutputCmd.h b/include/mcld/Script/OutputCmd.h
new file mode 100644
index 0000000..0a63891
--- /dev/null
+++ b/include/mcld/Script/OutputCmd.h
@@ -0,0 +1,50 @@
+//===- OutputCmd.h --------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OUTPUTCMD_H
+#define MCLD_SCRIPT_OUTPUTCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <string>
+
+namespace mcld
+{
+
+class Module;
+
+/** \class OutputCmd
+ * \brief This class defines the interfaces to Output command.
+ */
+
+class OutputCmd : public ScriptCommand
+{
+public:
+ OutputCmd(const std::string& pOutputFile);
+
+ ~OutputCmd();
+
+ void dump() const;
+
+ static bool classof(const ScriptCommand* pCmd)
+ {
+ return pCmd->getKind() == ScriptCommand::OUTPUT;
+ }
+
+ void activate(Module& pModule);
+
+private:
+ std::string m_OutputFile;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/OutputFormatCmd.h b/include/mcld/Script/OutputFormatCmd.h
new file mode 100644
index 0000000..b716e81
--- /dev/null
+++ b/include/mcld/Script/OutputFormatCmd.h
@@ -0,0 +1,63 @@
+//===- OutputFormatCmd.h --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OUTPUTFORMATCMD_H
+#define MCLD_SCRIPT_OUTPUTFORMATCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <string>
+#include <vector>
+
+namespace mcld
+{
+
+class Module;
+
+/** \class OutputFormatCmd
+ * \brief This class defines the interfaces to OutputFormat command.
+ */
+
+class OutputFormatCmd : public ScriptCommand
+{
+public:
+ typedef std::vector<std::string> FormatList;
+ typedef FormatList::const_iterator const_iterator;
+ typedef FormatList::iterator iterator;
+
+public:
+ OutputFormatCmd(const std::string& pFormat);
+ OutputFormatCmd(const std::string& pDefault,
+ const std::string& pBig,
+ const std::string& pLittle);
+ ~OutputFormatCmd();
+
+ const_iterator begin() const { return m_FormatList.begin(); }
+ iterator begin() { return m_FormatList.begin(); }
+ const_iterator end() const { return m_FormatList.end(); }
+ iterator end() { return m_FormatList.end(); }
+
+ void dump() const;
+
+ static bool classof(const ScriptCommand* pCmd)
+ {
+ return pCmd->getKind() == ScriptCommand::OUTPUT_FORMAT;
+ }
+
+ void activate(Module& pModule);
+
+private:
+ FormatList m_FormatList;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/OutputSectDesc.h b/include/mcld/Script/OutputSectDesc.h
new file mode 100644
index 0000000..3c5187b
--- /dev/null
+++ b/include/mcld/Script/OutputSectDesc.h
@@ -0,0 +1,214 @@
+//===- OutputSectDesc.h ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OUTPUTSECTDESC_H
+#define MCLD_SCRIPT_OUTPUTSECTDESC_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <vector>
+#include <string>
+#include <cassert>
+
+namespace mcld
+{
+
+class RpnExpr;
+class StringList;
+
+/** \class OutputSectDesc
+ * \brief This class defines the interfaces to output section description.
+ */
+
+class OutputSectDesc : public ScriptCommand
+{
+public:
+ enum Type {
+ LOAD, // ALLOC
+ NOLOAD,
+ DSECT,
+ COPY,
+ INFO,
+ OVERLAY
+ };
+
+ enum Constraint {
+ NO_CONSTRAINT,
+ ONLY_IF_RO,
+ ONLY_IF_RW
+ };
+
+ struct Prolog {
+ bool hasVMA() const { return m_pVMA != NULL; }
+ const RpnExpr& vma() const {
+ assert(hasVMA());
+ return *m_pVMA;
+ }
+ RpnExpr& vma() {
+ assert(hasVMA());
+ return *m_pVMA;
+ }
+
+ void setType(Type pType) {
+ m_Type = pType;
+ }
+
+ Type type() const { return m_Type; }
+
+ bool hasLMA() const { return m_pLMA != NULL; }
+ const RpnExpr& lma() const {
+ assert(hasLMA());
+ return *m_pLMA;
+ }
+ RpnExpr& lma() {
+ assert(hasLMA());
+ return *m_pLMA;
+ }
+
+ bool hasAlign() const { return m_pAlign != NULL; }
+ const RpnExpr& align() const {
+ assert(hasAlign());
+ return *m_pAlign;
+ }
+
+ bool hasSubAlign() const { return m_pSubAlign != NULL; }
+ const RpnExpr& subAlign() const {
+ assert(hasSubAlign());
+ return *m_pSubAlign;
+ }
+
+ Constraint constraint() const { return m_Constraint; }
+
+ bool operator==(const Prolog& pRHS) const {
+ /* FIXME: currently I don't check the real content */
+ if (this == &pRHS)
+ return true;
+ if (m_pVMA != pRHS.m_pVMA)
+ return false;
+ if (m_Type != pRHS.m_Type)
+ return false;
+ if (m_pLMA!= pRHS.m_pLMA)
+ return false;
+ if (m_pAlign != pRHS.m_pAlign)
+ return false;
+ if (m_pSubAlign != pRHS.m_pSubAlign)
+ return false;
+ if (m_Constraint != pRHS.m_Constraint)
+ return false;
+ return true;
+ }
+
+ RpnExpr* m_pVMA;
+ Type m_Type;
+ RpnExpr* m_pLMA;
+ RpnExpr* m_pAlign;
+ RpnExpr* m_pSubAlign;
+ Constraint m_Constraint;
+ };
+
+ struct Epilog {
+ bool hasRegion() const { return m_pRegion != NULL; }
+ const std::string& region() const {
+ assert(hasRegion());
+ return *m_pRegion;
+ }
+
+ bool hasLMARegion() const { return m_pLMARegion != NULL; }
+ const std::string& lmaRegion() const {
+ assert(hasLMARegion());
+ return *m_pLMARegion;
+ }
+
+ bool hasPhdrs() const { return m_pPhdrs != NULL; }
+ const StringList& phdrs() const {
+ assert(hasPhdrs());
+ return *m_pPhdrs;
+ }
+
+ bool hasFillExp() const { return m_pFillExp != NULL; }
+ const RpnExpr& fillExp() const {
+ assert(hasFillExp());
+ return *m_pFillExp;
+ }
+
+ bool operator==(const Epilog& pRHS) const {
+ /* FIXME: currently I don't check the real content */
+ if (this == &pRHS)
+ return true;
+ if (m_pRegion != pRHS.m_pRegion)
+ return false;
+ if (m_pLMARegion != pRHS.m_pLMARegion)
+ return false;
+ if (m_pPhdrs != pRHS.m_pPhdrs)
+ return false;
+ if (m_pFillExp != pRHS.m_pFillExp)
+ return false;
+ return true;
+ }
+
+ const std::string* m_pRegion;
+ const std::string* m_pLMARegion;
+ StringList* m_pPhdrs;
+ RpnExpr* m_pFillExp;
+ };
+
+ typedef std::vector<ScriptCommand*> OutputSectCmds;
+ typedef OutputSectCmds::const_iterator const_iterator;
+ typedef OutputSectCmds::iterator iterator;
+ typedef OutputSectCmds::const_reference const_reference;
+ typedef OutputSectCmds::reference reference;
+
+public:
+ OutputSectDesc(const std::string& pName, const Prolog& pProlog);
+ ~OutputSectDesc();
+
+ const_iterator begin() const { return m_OutputSectCmds.begin(); }
+ iterator begin() { return m_OutputSectCmds.begin(); }
+ const_iterator end() const { return m_OutputSectCmds.end(); }
+ iterator end() { return m_OutputSectCmds.end(); }
+
+ const_reference front() const { return m_OutputSectCmds.front(); }
+ reference front() { return m_OutputSectCmds.front(); }
+ const_reference back() const { return m_OutputSectCmds.back(); }
+ reference back() { return m_OutputSectCmds.back(); }
+
+ const std::string& name() const { return m_Name; }
+
+ size_t size() const { return m_OutputSectCmds.size(); }
+
+ bool empty() const { return m_OutputSectCmds.empty(); }
+
+ void dump() const;
+
+ static bool classof(const ScriptCommand* pCmd)
+ {
+ return pCmd->getKind() == ScriptCommand::OUTPUT_SECT_DESC;
+ }
+
+ void activate(Module& pModule);
+
+ void push_back(ScriptCommand* pCommand);
+
+ void setEpilog(const Epilog& pEpilog);
+
+ const Prolog& prolog() const { return m_Prolog; }
+
+ const Epilog& epilog() const { return m_Epilog; }
+
+private:
+ OutputSectCmds m_OutputSectCmds;
+ std::string m_Name;
+ Prolog m_Prolog;
+ Epilog m_Epilog;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Script/RpnEvaluator.h b/include/mcld/Script/RpnEvaluator.h
new file mode 100644
index 0000000..7e35e86
--- /dev/null
+++ b/include/mcld/Script/RpnEvaluator.h
@@ -0,0 +1,36 @@
+//===- RpnEvaluator.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_RPNEVALUATOR_H
+#define MCLD_SCRIPT_RPNEVALUATOR_H
+
+namespace mcld {
+
+class RpnExpr;
+class Module;
+class TargetLDBackend;
+
+/** \class RpnEvaluator
+ * \brief RpnEvaluator evaluate a rpn expression
+ */
+class RpnEvaluator
+{
+public:
+ RpnEvaluator(const Module& pModule, const TargetLDBackend& pBackend);
+
+ // evaluate a valid expression and set the value in the second parameter
+ bool eval(const RpnExpr& pExpr, uint64_t& pResult);
+
+private:
+ const Module& m_Module;
+ const TargetLDBackend& m_Backend;
+};
+
+} // mcld
+
+#endif
diff --git a/include/mcld/Script/RpnExpr.h b/include/mcld/Script/RpnExpr.h
new file mode 100644
index 0000000..96b11e9
--- /dev/null
+++ b/include/mcld/Script/RpnExpr.h
@@ -0,0 +1,81 @@
+//===- RPNExpr.h ----------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_RPNEXPR_H
+#define MCLD_SCRIPT_RPNEXPR_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
+#include <mcld/Object/SectionMap.h>
+#include <vector>
+
+namespace mcld
+{
+
+class ExprToken;
+class Fragment;
+
+/** \class RpnExpr
+ * \brief This class defines the interfaces to a rpn expression.
+ */
+
+class RpnExpr
+{
+public:
+ typedef std::vector<ExprToken*> TokenQueue;
+ typedef TokenQueue::const_iterator const_iterator;
+ typedef TokenQueue::iterator iterator;
+
+private:
+ friend class Chunk<RpnExpr, MCLD_SYMBOLS_PER_INPUT>;
+ RpnExpr();
+
+public:
+ ~RpnExpr();
+
+ const_iterator begin() const { return m_TokenQueue.begin(); }
+ iterator begin() { return m_TokenQueue.begin(); }
+ const_iterator end() const { return m_TokenQueue.end(); }
+ iterator end() { return m_TokenQueue.end(); }
+
+ size_t size() const { return m_TokenQueue.size(); }
+
+ bool empty() const { return m_TokenQueue.empty(); }
+
+ bool hasDot() const;
+
+ void dump() const;
+
+ void push_back(ExprToken* pToken);
+
+ iterator insert(iterator pPosition, ExprToken* pToken);
+
+ void erase(iterator pPosition);
+
+ /* factory methods */
+ static RpnExpr* create();
+ static void destroy(RpnExpr*& pRpnExpr);
+ static void clear();
+
+ // buildHelperExpr - build the helper expr:
+ // ADDR ( `output_sect' ) + SIZEOF ( `output_sect' )
+ static RpnExpr* buildHelperExpr(SectionMap::iterator pIter);
+ // buildHelperExpr - build the helper expr: `fragment'
+ static RpnExpr* buildHelperExpr(Fragment& pFrag);
+
+private:
+ TokenQueue m_TokenQueue;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/ScriptCommand.h b/include/mcld/Script/ScriptCommand.h
new file mode 100644
index 0000000..06e07eb
--- /dev/null
+++ b/include/mcld/Script/ScriptCommand.h
@@ -0,0 +1,60 @@
+//===- ScriptCommand.h ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_COMMAND_H
+#define MCLD_SCRIPT_COMMAND_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+namespace mcld {
+
+class Module;
+
+/** \class ScriptCommand
+ * \brief This class defines the interfaces to a script command.
+ */
+class ScriptCommand
+{
+public:
+ enum Kind {
+ ENTRY,
+ OUTPUT_FORMAT,
+ GROUP,
+ OUTPUT,
+ SEARCH_DIR,
+ OUTPUT_ARCH,
+ ASSERT,
+ ASSIGNMENT,
+ SECTIONS,
+ OUTPUT_SECT_DESC,
+ INPUT_SECT_DESC
+ };
+
+protected:
+ ScriptCommand(Kind pKind)
+ : m_Kind(pKind)
+ {}
+
+public:
+ virtual ~ScriptCommand() = 0;
+
+ virtual void dump() const = 0;
+
+ virtual void activate(Module&) = 0;
+
+ Kind getKind() const { return m_Kind; }
+
+private:
+ Kind m_Kind;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/ScriptFile.h b/include/mcld/Script/ScriptFile.h
new file mode 100644
index 0000000..03662e3
--- /dev/null
+++ b/include/mcld/Script/ScriptFile.h
@@ -0,0 +1,165 @@
+//===- ScriptFile.h -------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_SCRIPTFILE_H
+#define MCLD_SCRIPT_SCRIPTFILE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/Assignment.h>
+#include <mcld/Script/OutputSectDesc.h>
+#include <mcld/Script/InputSectDesc.h>
+#include <vector>
+#include <string>
+
+namespace mcld
+{
+
+class ScriptCommand;
+class Input;
+class InputTree;
+class InputBuilder;
+class GroupReader;
+class LinkerConfig;
+class RpnExpr;
+class StringList;
+class Module;
+
+/** \class ScriptFile
+ * \brief This class defines the interfaces to a linker script file.
+ */
+
+class ScriptFile
+{
+public:
+ enum Kind {
+ LDScript, // -T
+ Expression, // --defsym
+ VersionScript, // --version-script
+ DynamicList, // --dynamic-list
+ Unknown
+ };
+
+ typedef std::vector<ScriptCommand*> CommandQueue;
+ typedef CommandQueue::const_iterator const_iterator;
+ typedef CommandQueue::iterator iterator;
+ typedef CommandQueue::const_reference const_reference;
+ typedef CommandQueue::reference reference;
+
+public:
+ ScriptFile(Kind pKind, Input& pInput, InputBuilder& pBuilder);
+ ~ScriptFile();
+
+ const_iterator begin() const { return m_CommandQueue.begin(); }
+ iterator begin() { return m_CommandQueue.begin(); }
+ const_iterator end() const { return m_CommandQueue.end(); }
+ iterator end() { return m_CommandQueue.end(); }
+
+ const_reference front() const { return m_CommandQueue.front(); }
+ reference front() { return m_CommandQueue.front(); }
+ const_reference back() const { return m_CommandQueue.back(); }
+ reference back() { return m_CommandQueue.back(); }
+
+ const Input& input() const { return m_Input; }
+ Input& input() { return m_Input; }
+
+ size_t size() const { return m_CommandQueue.size(); }
+
+ Kind getKind() const { return m_Kind; }
+
+ const InputTree& inputs() const { return *m_pInputTree; }
+ InputTree& inputs() { return *m_pInputTree; }
+
+ const std::string& name() const { return m_Name; }
+ std::string& name() { return m_Name; }
+
+ void dump() const;
+ void activate(Module& pModule);
+
+ /// ENTRY(symbol)
+ void addEntryPoint(const std::string& pSymbol);
+
+ /// OUTPUT_FORMAT(bfdname)
+ /// OUTPUT_FORMAT(default, big, little)
+ void addOutputFormatCmd(const std::string& pFormat);
+ void addOutputFormatCmd(const std::string& pDefault,
+ const std::string& pBig,
+ const std::string& pLittle);
+
+ /// GROUP(file, file, ...)
+ /// GROUP(file file ...)
+ void addGroupCmd(StringList& pStringList,
+ GroupReader& pGroupReader,
+ const LinkerConfig& pConfig);
+
+ /// OUTPUT(filename)
+ void addOutputCmd(const std::string& pFileName);
+
+ /// SEARCH_DIR(path)
+ void addSearchDirCmd(const std::string& pPath);
+
+ /// OUTPUT_ARCH(bfdarch)
+ void addOutputArchCmd(const std::string& pArch);
+
+ /// ASSERT(exp, message)
+ void addAssertCmd(RpnExpr& pRpnExpr, const std::string& pMessage);
+
+ /// assignment
+ void addAssignment(const std::string& pSymbol,
+ RpnExpr& pRpnExpr,
+ Assignment::Type pType = Assignment::DEFAULT);
+
+ bool hasSectionsCmd() const;
+
+ void enterSectionsCmd();
+
+ void leaveSectionsCmd();
+
+ void enterOutputSectDesc(const std::string& pName,
+ const OutputSectDesc::Prolog& pProlog);
+
+ void leaveOutputSectDesc(const OutputSectDesc::Epilog& pEpilog);
+
+ void addInputSectDesc(InputSectDesc::KeepPolicy pPolicy,
+ const InputSectDesc::Spec& pSpec);
+
+ RpnExpr* createRpnExpr();
+ const RpnExpr* getCurrentRpnExpr() const { return m_pRpnExpr; }
+ RpnExpr* getCurrentRpnExpr() { return m_pRpnExpr; }
+
+ StringList* createStringList();
+ const StringList* getCurrentStringList() const { return m_pStringList; }
+ StringList* getCurrentStringList() { return m_pStringList; }
+
+ void setAsNeeded(bool pEnable = true);
+ bool asNeeded() const { return m_bAsNeeded; }
+
+ static const std::string& createParserStr(const char* pText, size_t pLength);
+
+ static void clearParserStrPool();
+
+private:
+ Kind m_Kind;
+ Input& m_Input;
+ std::string m_Name;
+ InputTree* m_pInputTree;
+ InputBuilder& m_Builder;
+ CommandQueue m_CommandQueue;
+ bool m_bHasSectionsCmd;
+ bool m_bInSectionsCmd;
+ bool m_bInOutputSectDesc;
+ RpnExpr* m_pRpnExpr;
+ StringList* m_pStringList;
+ bool m_bAsNeeded;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/ScriptReader.h b/include/mcld/Script/ScriptReader.h
new file mode 100644
index 0000000..14a667f
--- /dev/null
+++ b/include/mcld/Script/ScriptReader.h
@@ -0,0 +1,49 @@
+//===- ScriptReader.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_SCRIPTREADER_H
+#define MCLD_SCRIPT_SCRIPTREADER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/LD/LDReader.h>
+
+namespace mcld {
+
+class Module;
+class ScriptFile;
+class Input;
+class GroupReader;
+class LinkerConfig;
+class LinkerScript;
+class TargetLDBackend;
+
+class ScriptReader : public LDReader
+{
+public:
+ ScriptReader(GroupReader& pGroupReader);
+
+ ~ScriptReader();
+
+ /// readScript
+ bool readScript(const LinkerConfig& pConfig, ScriptFile& pScriptFile);
+
+ /// isMyFormat
+ bool isMyFormat(Input& pInput, bool &pContinue) const;
+
+ GroupReader& getGroupReader() { return m_GroupReader; }
+
+private:
+ GroupReader& m_GroupReader;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/ScriptScanner.h b/include/mcld/Script/ScriptScanner.h
new file mode 100644
index 0000000..43897e5
--- /dev/null
+++ b/include/mcld/Script/ScriptScanner.h
@@ -0,0 +1,62 @@
+//===- ScriptScanner.h ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_SCRIPTSCANNER_H
+#define MCLD_SCRIPT_SCRIPTSCANNER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#ifndef __FLEX_LEXER_H
+#include "FlexLexer.h"
+#endif
+
+#ifndef YY_DECL
+#define YY_DECL \
+ mcld::ScriptParser::token_type \
+ mcld::ScriptScanner::lex(mcld::ScriptParser::semantic_type* yylval, \
+ mcld::ScriptParser::location_type* yylloc, \
+ const mcld::ScriptFile& pScriptFile)
+#endif
+
+#include <mcld/Script/ScriptFile.h>
+#include "ScriptParser.h"
+#include <stack>
+
+namespace mcld {
+
+/** \class ScriptScanner
+ *
+ */
+class ScriptScanner : public yyFlexLexer
+{
+public:
+ ScriptScanner(std::istream* yyin = NULL, std::ostream* yyout = NULL);
+
+ virtual ~ScriptScanner();
+
+ virtual ScriptParser::token_type lex(ScriptParser::semantic_type* yylval,
+ ScriptParser::location_type* yylloc,
+ const ScriptFile& pScriptFile);
+
+ void setLexState(ScriptFile::Kind pKind);
+
+ void popLexState();
+
+private:
+ void enterComments(ScriptParser::location_type& pLocation);
+
+private:
+ ScriptFile::Kind m_Kind;
+ std::stack<ScriptFile::Kind> m_StateStack;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/SearchDirCmd.h b/include/mcld/Script/SearchDirCmd.h
new file mode 100644
index 0000000..f695a76
--- /dev/null
+++ b/include/mcld/Script/SearchDirCmd.h
@@ -0,0 +1,49 @@
+//===- SearchDirCmd.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_SEARCHDIRCMD_H
+#define MCLD_SCRIPT_SEARCHDIRCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <string>
+
+namespace mcld
+{
+
+class Module;
+
+/** \class SearchDirCmd
+ * \brief This class defines the interfaces to SEARCH_DIR command.
+ */
+
+class SearchDirCmd : public ScriptCommand
+{
+public:
+ SearchDirCmd(const std::string& pPath);
+ ~SearchDirCmd();
+
+ void dump() const;
+
+ void activate(Module& pModule);
+
+ static bool classof(const ScriptCommand* pCmd)
+ {
+ return pCmd->getKind() == ScriptCommand::SEARCH_DIR;
+ }
+
+private:
+ std::string m_Path;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/SectionsCmd.h b/include/mcld/Script/SectionsCmd.h
new file mode 100644
index 0000000..afff1b1
--- /dev/null
+++ b/include/mcld/Script/SectionsCmd.h
@@ -0,0 +1,72 @@
+//===- SectionsCmd.h ------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_SECTIONSCMD_H
+#define MCLD_SCRIPT_SECTIONSCMD_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/ScriptCommand.h>
+#include <llvm/Support/DataTypes.h>
+#include <vector>
+
+namespace mcld
+{
+
+class Module;
+
+/** \class SectionsCmd
+ * \brief This class defines the interfaces to SECTIONS command.
+ */
+
+class SectionsCmd : public ScriptCommand
+{
+public:
+ typedef std::vector<ScriptCommand*> SectionCommands;
+ typedef SectionCommands::const_iterator const_iterator;
+ typedef SectionCommands::iterator iterator;
+ typedef SectionCommands::const_reference const_reference;
+ typedef SectionCommands::reference reference;
+
+public:
+ SectionsCmd();
+ ~SectionsCmd();
+
+ const_iterator begin() const { return m_SectionCommands.begin(); }
+ iterator begin() { return m_SectionCommands.begin(); }
+ const_iterator end() const { return m_SectionCommands.end(); }
+ iterator end() { return m_SectionCommands.end(); }
+
+ const_reference front() const { return m_SectionCommands.front(); }
+ reference front() { return m_SectionCommands.front(); }
+ const_reference back() const { return m_SectionCommands.back(); }
+ reference back() { return m_SectionCommands.back(); }
+
+ size_t size() const { return m_SectionCommands.size(); }
+
+ bool empty() const { return m_SectionCommands.empty(); }
+
+ void dump() const;
+
+ static bool classof(const ScriptCommand* pCmd)
+ {
+ return pCmd->getKind() == ScriptCommand::SECTIONS;
+ }
+
+ void activate(Module& pModule);
+
+ void push_back(ScriptCommand* pCommand);
+
+private:
+ SectionCommands m_SectionCommands;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Script/StrToken.h b/include/mcld/Script/StrToken.h
new file mode 100644
index 0000000..359b0be
--- /dev/null
+++ b/include/mcld/Script/StrToken.h
@@ -0,0 +1,67 @@
+//===- StrToken.h ---------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_STRTOKEN_H
+#define MCLD_SCRIPT_STRTOKEN_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
+#include <string>
+
+namespace mcld
+{
+
+/** \class StrToken
+ * \brief This class defines the interfaces to a element in EXCLUDE_FILE list
+ * or in Output Section Phdr, or be a base class of other str token.
+ */
+
+class StrToken
+{
+public:
+ enum Kind {
+ Unknown,
+ String,
+ Input,
+ Wildcard
+ };
+
+private:
+ friend class Chunk<StrToken, MCLD_SYMBOLS_PER_INPUT>;
+protected:
+ StrToken();
+ StrToken(Kind pKind, const std::string& pString);
+
+public:
+ virtual ~StrToken();
+
+ Kind kind() const { return m_Kind; }
+
+ const std::string& name() const { return m_Name; }
+
+ static bool classof(const StrToken* pToken)
+ {
+ return pToken->kind() == StrToken::String;
+ }
+
+ /* factory method */
+ static StrToken* create(const std::string& pString);
+ static void destroy(StrToken*& pToken);
+ static void clear();
+
+private:
+ Kind m_Kind;
+ std::string m_Name;
+};
+
+} // namepsace of mcld
+
+#endif
diff --git a/include/mcld/Script/StringList.h b/include/mcld/Script/StringList.h
new file mode 100644
index 0000000..da27e41
--- /dev/null
+++ b/include/mcld/Script/StringList.h
@@ -0,0 +1,72 @@
+//===- StringList.h -------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_STRINGLIST_H
+#define MCLD_SCRIPT_STRINGLIST_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Config/Config.h>
+#include <mcld/Support/Allocators.h>
+#include <vector>
+
+namespace mcld
+{
+
+class StrToken;
+
+/** \class StringList
+ * \brief This class defines the interfaces to StringList.
+ */
+
+class StringList
+{
+public:
+ typedef std::vector<StrToken*> Tokens;
+ typedef Tokens::const_iterator const_iterator;
+ typedef Tokens::iterator iterator;
+ typedef Tokens::const_reference const_reference;
+ typedef Tokens::reference reference;
+
+private:
+ friend class Chunk<StringList, MCLD_SYMBOLS_PER_INPUT>;
+ StringList();
+
+public:
+ ~StringList();
+
+ const_iterator begin() const { return m_Tokens.begin(); }
+ iterator begin() { return m_Tokens.begin(); }
+ const_iterator end() const { return m_Tokens.end(); }
+ iterator end() { return m_Tokens.end(); }
+
+ const_reference front() const { return m_Tokens.front(); }
+ reference front() { return m_Tokens.front(); }
+ const_reference back() const { return m_Tokens.back(); }
+ reference back() { return m_Tokens.back(); }
+
+ bool empty() const { return m_Tokens.empty(); }
+
+ void push_back(StrToken* pToken);
+
+ void dump() const;
+
+ /* factory methods */
+ static StringList* create();
+ static void destroy(StringList*& pStringList);
+ static void clear();
+
+private:
+ Tokens m_Tokens;
+};
+
+} // namepsace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/TernaryOp.h b/include/mcld/Script/TernaryOp.h
new file mode 100644
index 0000000..0517b4a
--- /dev/null
+++ b/include/mcld/Script/TernaryOp.h
@@ -0,0 +1,71 @@
+//===- TernaryOp.h --------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_TERNARYOP_H
+#define MCLD_SCRIPT_TERNARYOP_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/Operator.h>
+#include <cstddef>
+
+namespace mcld
+{
+
+class Operand;
+class IntOperand;
+class Module;
+class TargetLDBackend;
+
+/** \class TernaryOP
+ * \brief This class defines the interfaces to an binary operator token.
+ */
+
+template<Operator::Type TYPE>
+class TernaryOp : public Operator
+{
+private:
+ friend class Operator;
+
+ TernaryOp()
+ : Operator(Operator::TERNARY, TYPE)
+ {
+ m_pOperand[0] = m_pOperand[1] = m_pOperand[2] = NULL;
+ }
+
+public:
+ ~TernaryOp()
+ {}
+
+ IntOperand* eval(const Module& pModule, const TargetLDBackend& pBackend);
+
+ void appendOperand(Operand* pOperand)
+ {
+ m_pOperand[m_Size++] = pOperand;
+ if (m_Size == 3)
+ m_Size = 0;
+ }
+
+private:
+ size_t m_Size;
+ Operand* m_pOperand[3];
+};
+
+template<>
+IntOperand* TernaryOp<Operator::TERNARY_IF>::eval(const Module&,
+ const TargetLDBackend&);
+
+template<>
+IntOperand*
+TernaryOp<Operator::DATA_SEGMENT_ALIGN>::eval(const Module&,
+ const TargetLDBackend&);
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Script/UnaryOp.h b/include/mcld/Script/UnaryOp.h
new file mode 100644
index 0000000..6b79b3c
--- /dev/null
+++ b/include/mcld/Script/UnaryOp.h
@@ -0,0 +1,102 @@
+//===- UnaryOp.h ----------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_UNARYOP_H
+#define MCLD_SCRIPT_UNARYOP_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/Operator.h>
+#include <cstddef>
+
+namespace mcld
+{
+
+class Operand;
+class IntOperand;
+class Module;
+class TargetLDBackend;
+
+/** \class UnaryOp
+ * \brief This class defines the interfaces to an unary operator token.
+ */
+
+template<Operator::Type TYPE>
+class UnaryOp : public Operator
+{
+private:
+ friend class Operator;
+
+ UnaryOp()
+ : Operator(Operator::UNARY, TYPE), m_pOperand(NULL)
+ {}
+
+public:
+ ~UnaryOp()
+ {}
+
+ IntOperand* eval(const Module& pModule, const TargetLDBackend& pBackend);
+
+ void appendOperand(Operand* pOperand)
+ {
+ m_pOperand = pOperand;
+ }
+
+private:
+ Operand* m_pOperand;
+};
+
+template<>
+IntOperand* UnaryOp<Operator::UNARY_PLUS>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::UNARY_MINUS>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::LOGICAL_NOT>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::BITWISE_NOT>::eval(const Module&,
+ const TargetLDBackend&);
+
+template<>
+IntOperand* UnaryOp<Operator::ABSOLUTE>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::ADDR>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::ALIGNOF>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::DATA_SEGMENT_END>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::DEFINED>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::LENGTH>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::LOADADDR>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::NEXT>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::ORIGIN>::eval(const Module&,
+ const TargetLDBackend&);
+template<>
+IntOperand* UnaryOp<Operator::SIZEOF>::eval(const Module&,
+ const TargetLDBackend&);
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Script/WildcardPattern.h b/include/mcld/Script/WildcardPattern.h
new file mode 100644
index 0000000..0c91435
--- /dev/null
+++ b/include/mcld/Script/WildcardPattern.h
@@ -0,0 +1,71 @@
+//===- WildcardPattern.h --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_WILDCARDPATTERN_H
+#define MCLD_SCRIPT_WILDCARDPATTERN_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Script/StrToken.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
+#include <llvm/ADT/StringRef.h>
+
+namespace mcld
+{
+
+/** \class WildcardPattern
+ * \brief This class defines the interfaces to Input Section Wildcard Patterns
+ */
+
+class WildcardPattern : public StrToken
+{
+public:
+ enum SortPolicy {
+ SORT_NONE,
+ SORT_BY_NAME,
+ SORT_BY_ALIGNMENT,
+ SORT_BY_NAME_ALIGNMENT,
+ SORT_BY_ALIGNMENT_NAME,
+ SORT_BY_INIT_PRIORITY
+ };
+
+private:
+ friend class Chunk<WildcardPattern, MCLD_SYMBOLS_PER_INPUT>;
+ WildcardPattern();
+ WildcardPattern(const std::string& pPattern, SortPolicy pPolicy);
+
+public:
+ ~WildcardPattern();
+
+ SortPolicy sortPolicy() const { return m_SortPolicy; }
+
+ bool isPrefix() const { return m_bIsPrefix; }
+
+ llvm::StringRef prefix() const;
+
+ static bool classof(const StrToken* pToken)
+ {
+ return pToken->kind() == StrToken::Wildcard;
+ }
+
+ /* factory method */
+ static WildcardPattern* create(const std::string& pPattern,
+ SortPolicy pPolicy);
+ static void destroy(WildcardPattern*& pToken);
+ static void clear();
+
+private:
+ SortPolicy m_SortPolicy;
+ bool m_bIsPrefix;
+};
+
+} // namepsace of mcld
+
+#endif
diff --git a/include/mcld/Support/CommandLine.h b/include/mcld/Support/CommandLine.h
index 00907fe..6cb0fae 100644
--- a/include/mcld/Support/CommandLine.h
+++ b/include/mcld/Support/CommandLine.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_COMMANDLINE_H
-#define MCLD_COMMANDLINE_H
+#ifndef MCLD_SUPPORT_COMMANDLINE_H
+#define MCLD_SUPPORT_COMMANDLINE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/DefSymParser.h b/include/mcld/Support/DefSymParser.h
deleted file mode 100644
index a721b48..0000000
--- a/include/mcld/Support/DefSymParser.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- DefSymParser.h -----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_DEFSYM_PARSER_H
-#define MCLD_DEFSYM_PARSER_H
-
-#include <mcld/Module.h>
-#include <llvm/ADT/StringRef.h>
-
-namespace mcld {
-
-/** \class DefSymParser
- * \brief DefSymParser parses --defsym option.
- */
-class DefSymParser
-{
-public:
- DefSymParser(const Module& pModule);
-
- // parse a valid expression and set the value in the second parameter
- bool parse(llvm::StringRef, uint64_t&);
-
-private:
- const Module& m_Module;
-};
-
-} // mcld
-
-#endif
diff --git a/include/mcld/Support/Directory.h b/include/mcld/Support/Directory.h
index 66ba118..2bf8f06 100644
--- a/include/mcld/Support/Directory.h
+++ b/include/mcld/Support/Directory.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_DIRECTORY_H
-#define MCLD_DIRECTORY_H
+#ifndef MCLD_SUPPORT_DIRECTORY_H
+#define MCLD_SUPPORT_DIRECTORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/FileHandle.h b/include/mcld/Support/FileHandle.h
index f9fe73a..9f551b9 100644
--- a/include/mcld/Support/FileHandle.h
+++ b/include/mcld/Support/FileHandle.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_FILE_HANDLE_H
-#define MCLD_FILE_HANDLE_H
+#ifndef MCLD_SUPPORT_FILEHANDLE_H
+#define MCLD_SUPPORT_FILEHANDLE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/FileOutputBuffer.h b/include/mcld/Support/FileOutputBuffer.h
new file mode 100644
index 0000000..a49ffb7
--- /dev/null
+++ b/include/mcld/Support/FileOutputBuffer.h
@@ -0,0 +1,72 @@
+//===- FileOutputBuffer.h -------------------------------------------------===//
+//
+// the mclinker project
+//
+// this file is distributed under the university of illinois open source
+// license. see license.txt for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SUPPORT_FILEOUTPUTBUFFER_H
+#define MCLD_SUPPORT_FILEOUTPUTBUFFER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Support/MemoryRegion.h>
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/DataTypes.h>
+#include <llvm/Support/FileSystem.h>
+#include <llvm/Support/system_error.h>
+
+namespace mcld {
+
+class FileHandle;
+
+/// FileOutputBuffer - This interface is borrowed from llvm bassically, and we
+/// may use ostream to emit output later.
+class FileOutputBuffer {
+public:
+ /// Factory method to create an OutputBuffer object which manages a read/write
+ /// buffer of the specified size. When committed, the buffer will be written
+ /// to the file at the specified path.
+ static llvm::error_code create(FileHandle& pFileHandle,
+ size_t pSize,
+ llvm::OwningPtr<FileOutputBuffer>& pResult);
+
+ /// Returns a pointer to the start of the buffer.
+ uint8_t* getBufferStart() {
+ return (uint8_t*)m_pRegion->data();
+ }
+
+ /// Returns a pointer to the end of the buffer.
+ uint8_t* getBufferEnd() {
+ return (uint8_t*)m_pRegion->data() + m_pRegion->size();
+ }
+
+ /// Returns size of the buffer.
+ size_t getBufferSize() const {
+ return m_pRegion->size();
+ }
+
+ MemoryRegion request(size_t pOffset, size_t pLength);
+
+ /// Returns path where file will show up if buffer is committed.
+ llvm::StringRef getPath() const;
+
+ ~FileOutputBuffer();
+
+private:
+ FileOutputBuffer(const FileOutputBuffer &);
+ FileOutputBuffer &operator=(const FileOutputBuffer &);
+
+ FileOutputBuffer(llvm::sys::fs::mapped_file_region* pRegion,
+ FileHandle& pFileHandle);
+
+ llvm::OwningPtr<llvm::sys::fs::mapped_file_region> m_pRegion;
+ FileHandle& m_FileHandle;
+};
+
+} // namespace mcld
+
+#endif
diff --git a/include/mcld/Support/FileSystem.h b/include/mcld/Support/FileSystem.h
index 927346e..e0dddd7 100644
--- a/include/mcld/Support/FileSystem.h
+++ b/include/mcld/Support/FileSystem.h
@@ -11,8 +11,8 @@
// path class.
//===----------------------------------------------------------------------===//
-#ifndef MCLD_FILE_SYSTEM_H
-#define MCLD_FILE_SYSTEM_H
+#ifndef MCLD_SUPPORT_FILESYSTEM_H
+#define MCLD_SUPPORT_FILESYSTEM_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/GCFactory.h b/include/mcld/Support/GCFactory.h
index 6679f41..9ae8650 100644
--- a/include/mcld/Support/GCFactory.h
+++ b/include/mcld/Support/GCFactory.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_GC_FACTORY_H
-#define MCLD_GC_FACTORY_H
+#ifndef MCLD_SUPPORT_GCFACTORY_H
+#define MCLD_SUPPORT_GCFACTORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/GCFactoryListTraits.h b/include/mcld/Support/GCFactoryListTraits.h
index 986f6f6..b7d44d3 100644
--- a/include/mcld/Support/GCFactoryListTraits.h
+++ b/include/mcld/Support/GCFactoryListTraits.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_GC_FACTORY_LIST_TRAITS_H
-#define MCLD_GC_FACTORY_LIST_TRAITS_H
+#ifndef MCLD_SUPPORT_GCFACTORYLISTTRAITS_H
+#define MCLD_SUPPORT_GCFACTORYLISTTRAITS_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/HandleToArea.h b/include/mcld/Support/HandleToArea.h
deleted file mode 100644
index 8c24db7..0000000
--- a/include/mcld/Support/HandleToArea.h
+++ /dev/null
@@ -1,118 +0,0 @@
-//===- HandleToArea.h -----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_FILE_HANDLE_TO_MEMORY_AREA_H
-#define MCLD_FILE_HANDLE_TO_MEMORY_AREA_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/ADT/Uncopyable.h>
-#include <mcld/ADT/TypeTraits.h>
-#include <mcld/ADT/StringHash.h>
-#include <mcld/Support/Path.h>
-#include <mcld/Support/FileHandle.h>
-#include <vector>
-
-namespace mcld {
-
-class MemoryArea;
-
-/** \class HandleToArea
- *
- * Special double-key associative container. Keys are Path and file handler,
- * associative value is MemoryArea.
- *
- * For high performance, HandleToArea is not designed to contain unique
- * <key, value> pair. The key and value may be duplicated.
- *
- * Like FileHandle, HandleToArea should neither throw exception nor call
- * expressive diagnostic.
- */
-class HandleToArea : private Uncopyable
-{
-private:
- struct Bucket {
- unsigned int hash_value;
- FileHandle* handle;
- MemoryArea* area;
- };
-
- // the best data structure is a binary search tree.
- // However, by the shrinking time-to-market constraint, I used
- // vector and sequential search here.
- typedef std::vector<Bucket> HandleToAreaMap;
-
- typedef hash::StringHash<hash::BKDR> HashFunction;
-
-public:
- typedef HandleToAreaMap::iterator iterator;
- typedef HandleToAreaMap::const_iterator const_iterator;
-
-public:
- struct Result {
- public:
- Result(FileHandle* pHandle, MemoryArea* pArea)
- : handle(pHandle), area(pArea) { }
-
- public:
- FileHandle* handle;
- MemoryArea* area;
- };
-
- struct ConstResult {
- public:
- ConstResult(const FileHandle* pHandle, const MemoryArea* pArea)
- : handle(pHandle), area(pArea) { }
-
- public:
- const FileHandle* handle;
- const MemoryArea* area;
- };
-
-public:
- bool push_back(FileHandle* pHandle, MemoryArea* pArea);
-
- bool erase(MemoryArea* pArea);
-
- bool erase(const sys::fs::Path& pPath);
-
- Result findFirst(const sys::fs::Path& pPath);
-
- ConstResult findFirst(const sys::fs::Path& pPath) const;
-
- iterator begin()
- { return m_AreaMap.begin(); }
-
- iterator end()
- { return m_AreaMap.end(); }
-
- const_iterator begin() const
- { return m_AreaMap.begin(); }
-
- const_iterator end() const
- { return m_AreaMap.end(); }
-
- // ----- capacity ----- //
- bool empty() const
- { return m_AreaMap.empty(); }
-
- size_t size() const
- { return m_AreaMap.size(); }
-
- HandleToArea() : m_AreaMap() { }
-
- ~HandleToArea() { }
-
-private:
- HandleToAreaMap m_AreaMap;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Support/LEB128.h b/include/mcld/Support/LEB128.h
index 816ed72..e44966a 100644
--- a/include/mcld/Support/LEB128.h
+++ b/include/mcld/Support/LEB128.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LEB128_H
-#define MCLD_LEB128_H
+#ifndef MCLD_SUPPORT_LEB128_H
+#define MCLD_SUPPORT_LEB128_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/MemoryArea.h b/include/mcld/Support/MemoryArea.h
index d3ae9b7..18ea985 100644
--- a/include/mcld/Support/MemoryArea.h
+++ b/include/mcld/Support/MemoryArea.h
@@ -6,43 +6,22 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_SUPPORT_MEMORY_AREA_H
-#define MCLD_SUPPORT_MEMORY_AREA_H
+#ifndef MCLD_SUPPORT_MEMORYAREA_H
+#define MCLD_SUPPORT_MEMORYAREA_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <mcld/ADT/Uncopyable.h>
-#include <cstddef>
-#include <map>
-#if defined(ENABLE_UNITTEST)
-namespace mcldtest {
- class MemoryAreaTest;
-} // namespace of mcldtest
-#endif
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/MemoryBuffer.h>
namespace mcld {
-class Space;
-class FileHandle;
-class MemoryRegion;
-
/** \class MemoryArea
- * \brief MemoryArea is used to manage distinct MemoryRegions of address space.
- *
- * Good linkers must well manipulate memory mapped I/O and dynamic memory.
- * In MCLinker, MemoryArea is the decision-maker to use memory mapped I/O or
- * dynamic memory. When a client requests MemoryArea for a piece of memory
- * to hold a part of a file, MemoryArea is going to see whether the requested
- * part of the file is already in any existing memory which is requested
- * before. If it is, MemoryArea creates a new MemoryRegion within the memory
- * requested before. Otherwise, MemoryArea uses memory mapped I/O or dynamic
- * memory to load the file.
- *
- * If the part a file being loaded is larger than 3/4 pages, MemoryArea uses
- * memory mapped I/O to load the file. Otherwise, MemoryArea uses dynamic
- * memory to read the content of file into the memory space.
+ * \brief MemoryArea is used to manage input read-only memory space.
*/
class MemoryArea : private Uncopyable
{
@@ -52,72 +31,22 @@
// If the given file handler is read-only, client can not request a region
// that out of the file size.
// @param pFileHandle - file handler
- explicit MemoryArea(FileHandle& pFileHandle);
+ explicit MemoryArea(llvm::StringRef pFilename);
- // constructor by set universal space.
- // Client can not request a region that out of the universal space.
- // @param pUniverse - file handler
- explicit MemoryArea(Space& pUniverse);
-
- // destructor
- ~MemoryArea();
+ explicit MemoryArea(const char* pMemBuffer, size_t pSize);
// request - create a MemoryRegion within a sufficient space
// find an existing space to hold the MemoryRegion.
// if MemoryArea does not find such space, then it creates a new space and
// assign a MemoryRegion into the space.
- MemoryRegion* request(size_t pOffset, size_t pLength);
+ llvm::StringRef request(size_t pOffset, size_t pLength);
- // release - release a MemoryRegion.
- // release a MemoryRegion does not cause
- void release(MemoryRegion* pRegion);
-
- // clear - release all memory regions.
- void clear();
-
- const FileHandle* handler() const { return m_pFileHandle; }
- FileHandle* handler() { return m_pFileHandle; }
-
- bool hasHandler() const { return (NULL != m_pFileHandle); }
-
- // ----- space list methods ----- //
- Space* find(size_t pOffset, size_t pLength);
-
- const Space* find(size_t pOffset, size_t pLength) const;
+ size_t size() const;
private:
- class Key {
- public:
- Key(size_t pOffset, size_t pLength)
- : m_Offset(pOffset), m_Length(pLength)
- { }
-
- size_t offset() const { return m_Offset; }
-
- size_t length() const { return m_Length; }
-
- struct Compare {
- bool operator()(const Key& KEY1, const Key& KEY2) const
- {
- return KEY1.offset() + KEY1.length() < KEY2.offset() ||
- (KEY1.offset() < KEY2.offset() &&
- (KEY1.offset() + KEY1.length() < KEY2.offset() + KEY2.length()));
- }
- };
-
- private:
- size_t m_Offset;
- size_t m_Length;
- };
-
- typedef std::multimap<Key, Space*, Key::Compare> SpaceMapType;
-
-private:
- SpaceMapType m_SpaceMap;
- FileHandle* m_pFileHandle;
+ llvm::OwningPtr<llvm::MemoryBuffer> m_pMemoryBuffer;
};
} // namespace of mcld
#endif
-
diff --git a/include/mcld/Support/MemoryAreaFactory.h b/include/mcld/Support/MemoryAreaFactory.h
index b28f096..302fbd1 100644
--- a/include/mcld/Support/MemoryAreaFactory.h
+++ b/include/mcld/Support/MemoryAreaFactory.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_SUPPORT_MEMORY_AREA_FACTORY_H
-#define MCLD_SUPPORT_MEMORY_AREA_FACTORY_H
+#ifndef MCLD_SUPPORT_MEMORYAREAFACTORY_H
+#define MCLD_SUPPORT_MEMORYAREAFACTORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -15,7 +15,7 @@
#include <mcld/Support/MemoryArea.h>
#include <mcld/Support/Path.h>
#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/HandleToArea.h>
+#include <llvm/ADT/StringMap.h>
namespace mcld
{
@@ -63,12 +63,10 @@
MemoryArea* produce(int pFD, FileHandle::OpenMode pMode);
void destruct(MemoryArea* pArea);
-
private:
- HandleToArea m_HandleToArea;
+ llvm::StringMap<MemoryArea*> m_AreaMap;
};
} // namespace of mcld
#endif
-
diff --git a/include/mcld/Support/MemoryRegion.h b/include/mcld/Support/MemoryRegion.h
index 0984873..0d18f59 100644
--- a/include/mcld/Support/MemoryRegion.h
+++ b/include/mcld/Support/MemoryRegion.h
@@ -6,112 +6,24 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef LD_MEMORY_REGION_H
-#define LD_MEMORY_REGION_H
+#ifndef MCLD_SUPPORT_MEMORYREGION_H
+#define MCLD_SUPPORT_MEMORYREGION_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <mcld/Config/Config.h>
-#include <mcld/ADT/Uncopyable.h>
-#include <mcld/Support/Allocators.h>
-#include <mcld/Support/Space.h>
+#include <mcld/ADT/TypeTraits.h>
+#include <llvm/ADT/ArrayRef.h>
+#include <llvm/Support/DataTypes.h>
namespace mcld {
-class MemoryArea;
+typedef NonConstTraits<uint8_t>::pointer Address;
+typedef ConstTraits<uint8_t>::pointer ConstAddress;
-/** \class MemoryRegion
- * \brief MemoryRegion is a range of virtual memory which is mapped onto a
- * range of files which is opened by MemoryArea.
- *
- * MemoryArea maps a file onto virtual memory. Clients can get a range of
- * mapped memory space by requesting a MemoryRegion from MemoryArea, and
- * read/write the mapped file through the MemoryRegion.
- *
- * When two different MemoryRegion may overlap memory space, race condition
- * may occurs. Clients must call MemoryRegion::sync() explicit to tell the
- * MemoryArea when to synchronize the virtual memory space with the mapped
- * file.
- */
-class MemoryRegion : private Uncopyable
-{
-friend class Chunk<MemoryRegion, MCLD_REGION_CHUNK_SIZE>;
-friend class RegionFactory;
-friend class MemoryArea;
+typedef llvm::ArrayRef<uint8_t> ConstMemoryRegion;
+typedef llvm::MutableArrayRef<uint8_t> MemoryRegion;
-public:
- typedef Space::Address Address;
- typedef Space::ConstAddress ConstAddress;
-
-private:
- MemoryRegion();
-
- MemoryRegion(const Address pVMAStart, size_t pSize);
-
- ~MemoryRegion();
-
- void setParent(Space& pSpace) { m_pParent = &pSpace; }
-
-public:
- /// Create - To wrap a piece of memory and to create a new region.
- /// This function wraps a piece of memory and to create a new region. Region
- /// is just a wraper, it is not responsible for deallocate the given memory.
- ///
- /// @param pStart [in] The start address of a piece of memory
- /// @param pSize [in] The size of the given memory
- static MemoryRegion* Create(void* pStart, size_t pSize);
-
- /// Create - To wrap a piece of memory and to create a new region.
- /// This function wraps a piece of memory and to create a new region. Region
- /// is just a wraper, it is not responsible for deallocate the given memory.
- ///
- /// If a wrapped memory comes from a Space, then we say the space is the
- /// parent of the region. pSpace is a memory counting container. It remembers
- /// the number of regions in it. A space which has no region will be removed
- /// quickly.
- ///
- /// The wrapped memory will be deallocated by Space when the space has no
- /// region used it.
- ///
- /// @param pStart [in] The start address of a piece of memory
- /// @param pSize [in] The size of the given memory
- /// @param pSpace [in] The parent space.
- static MemoryRegion* Create(void* pStart, size_t pSize, Space& pSpace);
-
- /// Destroy - To destroy the region
- /// If the region has a parent space, it will be also remove from the space.
- ///
- /// @param pRegion [in, out] pRegion is set to NULL if the destruction is
- /// success.
- static void Destroy(MemoryRegion*& pRegion);
-
- const Space* parent() const { return m_pParent; }
- Space* parent() { return m_pParent; }
-
- bool hasParent() const { return (NULL != m_pParent); }
-
- ConstAddress start() const { return m_VMAStart; }
- Address start() { return m_VMAStart; }
-
- ConstAddress end() const { return m_VMAStart+m_Length; }
- Address end() { return m_VMAStart+m_Length; }
-
- size_t size() const { return m_Length; }
-
- ConstAddress getBuffer(size_t pOffset = 0) const
- { return m_VMAStart+pOffset; }
-
- Address getBuffer(size_t pOffset = 0)
- { return m_VMAStart+pOffset; }
-
-private:
- Space* m_pParent;
- Address m_VMAStart;
- size_t m_Length;
-};
-
-} // namespace of mcld
+} // namespace mcld
#endif
-
diff --git a/include/mcld/Support/MsgHandling.h b/include/mcld/Support/MsgHandling.h
index d00132c..778ec68 100644
--- a/include/mcld/Support/MsgHandling.h
+++ b/include/mcld/Support/MsgHandling.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_MESSAGE_HANDLING_H
-#define MCLD_MESSAGE_HANDLING_H
+#ifndef MCLD_SUPPORT_MSGHANDLING_H
+#define MCLD_SUPPORT_MSGHANDLING_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/Path.h b/include/mcld/Support/Path.h
index 13e8ddb..fe7914e 100644
--- a/include/mcld/Support/Path.h
+++ b/include/mcld/Support/Path.h
@@ -10,8 +10,8 @@
// filesystem (v3), but modified to remove exception handling and the
// path class.
//===----------------------------------------------------------------------===//
-#ifndef MCLD_PATH_H
-#define MCLD_PATH_H
+#ifndef MCLD_SUPPORT_PATH_H
+#define MCLD_SUPPORT_PATH_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/PathCache.h b/include/mcld/Support/PathCache.h
index 50c6984..37857dc 100644
--- a/include/mcld/Support/PathCache.h
+++ b/include/mcld/Support/PathCache.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_PATHCACHE_H
-#define MCLD_PATHCACHE_H
+#ifndef MCLD_SUPPORT_PATHCACHE_H
+#define MCLD_SUPPORT_PATHCACHE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/RealPath.h b/include/mcld/Support/RealPath.h
index 6c0cd40..0369f25 100644
--- a/include/mcld/Support/RealPath.h
+++ b/include/mcld/Support/RealPath.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_REAL_PATH_H
-#define MCLD_REAL_PATH_H
+#ifndef MCLD_SUPPORT_REALPATH_H
+#define MCLD_SUPPORT_REALPATH_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/RegionFactory.h b/include/mcld/Support/RegionFactory.h
deleted file mode 100644
index fd90186..0000000
--- a/include/mcld/Support/RegionFactory.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//===- RegionFactory.h ----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_SUPPORT_REGION_FACTORY_H
-#define MCLD_SUPPORT_REGION_FACTORY_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/Config/Config.h>
-#include <mcld/Support/GCFactory.h>
-#include <mcld/Support/MemoryRegion.h>
-
-namespace mcld {
-
-class MemoryArea;
-
-/** \class RegionFactory
- * \brief RegionFactory produces and destroys MemoryRegions
- *
- */
-class RegionFactory : public GCFactory<MemoryRegion, MCLD_REGION_CHUNK_SIZE>
-{
-public:
- typedef GCFactory<MemoryRegion, MCLD_REGION_CHUNK_SIZE> Alloc;
- typedef MemoryRegion::Address Address;
- typedef MemoryRegion::ConstAddress ConstAddress;
-
-public:
- MemoryRegion* produce(Address pVMAStart, size_t pSize);
-
- void destruct(MemoryRegion* pRegion);
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Support/Space.h b/include/mcld/Support/Space.h
deleted file mode 100644
index cdf69b0..0000000
--- a/include/mcld/Support/Space.h
+++ /dev/null
@@ -1,99 +0,0 @@
-//===- Space.h ------------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_MEMORY_SPACE_H
-#define MCLD_MEMORY_SPACE_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <llvm/Support/DataTypes.h>
-#include <mcld/ADT/TypeTraits.h>
-
-namespace mcld {
-
-class FileHandle;
-class MemoryRegion;
-
-/** \class Space
- * \brief Space contains a chunk of memory space that does not overlap with
- * the other Space.
- *
- */
-class Space
-{
-public:
- enum Type
- {
- ALLOCATED_ARRAY,
- MMAPED,
- EXTERNAL,
- UNALLOCATED
- };
-
- typedef NonConstTraits<uint8_t>::pointer Address;
- typedef ConstTraits<uint8_t>::pointer ConstAddress;
-
-private:
- Space();
-
- ~Space();
-
- Space(Type pType, void* pMemBuffer, size_t pSize);
-
-public:
- void setStart(size_t pOffset)
- { m_StartOffset = pOffset; }
-
- Address memory()
- { return m_Data; }
-
- ConstAddress memory() const
- { return m_Data; }
-
- size_t start() const
- { return m_StartOffset; }
-
- size_t size() const
- { return m_Size; }
-
- Type type() const
- { return m_Type; }
-
- void addRegion(MemoryRegion& pRegion)
- { ++m_RegionCount; }
-
- void removeRegion(MemoryRegion& pRegion)
- { --m_RegionCount; }
-
- size_t numOfRegions() const
- { return m_RegionCount; }
-
- /// Create - Create a Space from external memory
- static Space* Create(void* pMemBuffer, size_t pSize);
-
- /// Create - Create a Space from FileHandler
- static Space* Create(FileHandle& pHandler, size_t pOffset, size_t pSize);
-
- static void Destroy(Space*& pSpace);
-
- static void Release(Space* pSpace, FileHandle& pHandler);
-
- static void Sync(Space* pSpace, FileHandle& pHandler);
-
-private:
- Address m_Data;
- uint32_t m_StartOffset;
- uint32_t m_Size;
- uint16_t m_RegionCount;
- Type m_Type : 2;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Support/SystemUtils.h b/include/mcld/Support/SystemUtils.h
index 8f8507a..f15fccf 100644
--- a/include/mcld/Support/SystemUtils.h
+++ b/include/mcld/Support/SystemUtils.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_SYSTEM_UTILS_H
-#define MCLD_SYSTEM_UTILS_H
+#ifndef MCLD_SUPPORT_SYSTEMUTILS_H
+#define MCLD_SUPPORT_SYSTEMUTILS_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/Target.h b/include/mcld/Support/Target.h
new file mode 100644
index 0000000..021fc2e
--- /dev/null
+++ b/include/mcld/Support/Target.h
@@ -0,0 +1,105 @@
+//===- Target.h -----------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SUPPORT_TARGET_H
+#define MCLD_SUPPORT_TARGET_H
+#include <string>
+#include <list>
+
+namespace llvm {
+class Target;
+class Triple;
+class TargetMachine;
+} // namespace of llvm
+
+namespace mcld {
+
+class MCLDTargetMachine;
+class TargetRegistry;
+class MCLinker;
+class LinkerScript;
+class LinkerConfig;
+class Module;
+class FileHandle;
+class DiagnosticLineInfo;
+class TargetLDBackend;
+
+/** \class Target
+ * \brief Target collects target specific information
+ */
+class Target
+{
+ friend class mcld::MCLDTargetMachine;
+ friend class mcld::TargetRegistry;
+
+public:
+ typedef unsigned int (*TripleMatchQualityFnTy)(const llvm::Triple& pTriple);
+
+ typedef MCLDTargetMachine *(*TargetMachineCtorTy)(const llvm::Target &,
+ const mcld::Target &,
+ llvm::TargetMachine &,
+ const std::string&);
+
+ typedef MCLinker *(*MCLinkerCtorTy)(const std::string& pTriple,
+ LinkerConfig&,
+ Module&,
+ FileHandle& pFileHandle);
+
+ typedef bool (*EmulationFnTy)(LinkerScript&, LinkerConfig&);
+
+ typedef TargetLDBackend *(*TargetLDBackendCtorTy)(const LinkerConfig&);
+
+ typedef DiagnosticLineInfo *(*DiagnosticLineInfoCtorTy)(const mcld::Target&,
+ const std::string&);
+
+public:
+ Target();
+
+ /// getName - get the target name
+ const char* name() const { return Name; }
+
+ unsigned int getTripleQuality(const llvm::Triple& pTriple) const;
+
+ /// createTargetMachine - create target-specific TargetMachine
+ MCLDTargetMachine* createTargetMachine(const std::string& pTriple,
+ const llvm::Target& pTarget,
+ llvm::TargetMachine& pTM) const;
+
+ /// createMCLinker - create target-specific MCLinker
+ MCLinker *createMCLinker(const std::string &pTriple,
+ LinkerConfig& pConfig,
+ Module& pModule,
+ FileHandle& pFileHandle) const;
+
+ /// emulate - given MCLinker default values for the other aspects of the
+ /// target system.
+ bool emulate(LinkerScript& pScript, LinkerConfig& pConfig) const;
+
+ /// createLDBackend - create target-specific LDBackend
+ TargetLDBackend* createLDBackend(const LinkerConfig& pConfig) const;
+
+ /// createDiagnosticLineInfo - create target-specific DiagnosticLineInfo
+ DiagnosticLineInfo* createDiagnosticLineInfo(const mcld::Target& pTarget,
+ const std::string& pTriple) const;
+
+private:
+ /// Name - The target name
+ const char* Name;
+
+ TripleMatchQualityFnTy TripleMatchQualityFn;
+ TargetMachineCtorTy TargetMachineCtorFn;
+ MCLinkerCtorTy MCLinkerCtorFn;
+ EmulationFnTy EmulationFn;
+ TargetLDBackendCtorTy TargetLDBackendCtorFn;
+ DiagnosticLineInfoCtorTy DiagnosticLineInfoCtorFn;
+};
+
+} //end namespace mcld
+
+#endif
+
diff --git a/include/mcld/Support/TargetRegistry.h b/include/mcld/Support/TargetRegistry.h
index aabb06d..1ae6245 100644
--- a/include/mcld/Support/TargetRegistry.h
+++ b/include/mcld/Support/TargetRegistry.h
@@ -6,9 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_REGISTRY_H
-#define MCLD_TARGET_REGISTRY_H
-#include <llvm/Support/TargetRegistry.h>
+#ifndef MCLD_SUPPORT_TARGETREGISTRY_H
+#define MCLD_SUPPORT_TARGETREGISTRY_H
+#include <mcld/Support/Target.h>
+#include <llvm/ADT/Triple.h>
+
#include <string>
#include <list>
@@ -21,122 +23,9 @@
namespace mcld {
-class Module;
-class LinkerConfig;
-class LinkerScript;
-class MemoryArea;
-class MCLDTargetMachine;
-class TargetRegistry;
-class MCLinker;
-class TargetLDBackend;
-class AttributeFactory;
-class InputFactory;
-class ContextFactory;
-class DiagnosticLineInfo;
-
-//===----------------------------------------------------------------------===//
-/// Target - mcld::Target is an object adapter of llvm::Target
-//===----------------------------------------------------------------------===//
-class Target
-{
- friend class mcld::MCLDTargetMachine;
- friend class mcld::TargetRegistry;
-public:
- typedef mcld::MCLDTargetMachine *(*TargetMachineCtorTy)(const mcld::Target &,
- llvm::TargetMachine &,
- const std::string&);
-
- typedef MCLinker *(*MCLinkerCtorTy)(const std::string& pTriple,
- LinkerConfig&,
- Module&,
- MemoryArea& pOutput);
-
- typedef bool (*EmulationFnTy)(LinkerScript&, LinkerConfig&);
-
- typedef TargetLDBackend *(*TargetLDBackendCtorTy)(const llvm::Target&,
- const LinkerConfig&);
-
- typedef DiagnosticLineInfo *(*DiagnosticLineInfoCtorTy)(const mcld::Target&,
- const std::string&);
-
-public:
- Target();
-
- void setTarget(const llvm::Target& pTarget)
- { m_pT = &pTarget; }
-
- mcld::MCLDTargetMachine *createTargetMachine(const std::string &pTriple,
- const std::string &pCPU, const std::string &pFeatures,
- const llvm::TargetOptions &Options,
- llvm::Reloc::Model RM = llvm::Reloc::Default,
- llvm::CodeModel::Model CM = llvm::CodeModel::Default,
- llvm::CodeGenOpt::Level OL = llvm::CodeGenOpt::Default) const
- {
- if (TargetMachineCtorFn && m_pT) {
- llvm::TargetMachine *tm = m_pT->createTargetMachine(pTriple, pCPU, pFeatures, Options, RM, CM, OL);
- if (tm)
- return TargetMachineCtorFn(*this, *tm, pTriple);
- }
- return NULL;
- }
-
- /// createMCLinker - create target-specific MCLinker
- ///
- /// @return created MCLinker
- MCLinker *createMCLinker(const std::string &pTriple,
- LinkerConfig& pConfig,
- Module& pModule,
- MemoryArea& pOutput) const {
- if (!MCLinkerCtorFn)
- return NULL;
- return MCLinkerCtorFn(pTriple, pConfig, pModule, pOutput);
- }
-
- /// emulate - given MCLinker default values for the other aspects of the
- /// target system.
- bool emulate(LinkerScript& pScript, LinkerConfig& pConfig) const {
- if (!EmulationFn)
- return false;
- return EmulationFn(pScript, pConfig);
- }
-
- /// createLDBackend - create target-specific LDBackend
- ///
- /// @return created TargetLDBackend
- TargetLDBackend* createLDBackend(const LinkerConfig& pConfig) const
- {
- if (!TargetLDBackendCtorFn)
- return NULL;
- return TargetLDBackendCtorFn(*get(), pConfig);
- }
-
- /// createDiagnosticLineInfo - create target-specific DiagnosticLineInfo
- DiagnosticLineInfo* createDiagnosticLineInfo(const mcld::Target& pTarget,
- const std::string& pTriple) const
- {
- if (!DiagnosticLineInfoCtorFn)
- return NULL;
- return DiagnosticLineInfoCtorFn(pTarget, pTriple);
- }
-
- const llvm::Target* get() const { return m_pT; }
-
-private:
- // ----- function pointers ----- //
- TargetMachineCtorTy TargetMachineCtorFn;
- MCLinkerCtorTy MCLinkerCtorFn;
- EmulationFnTy EmulationFn;
- TargetLDBackendCtorTy TargetLDBackendCtorFn;
- DiagnosticLineInfoCtorTy DiagnosticLineInfoCtorFn;
-
- // ----- adapted llvm::Target ----- //
- const llvm::Target* m_pT;
-};
-
-//===----------------------------------------------------------------------===//
-/// TargetRegistry - mcld::TargetRegistry is an object adapter of
-/// llvm::TargetRegistry
-///
+/** \class TargetRegistry
+ * \brief TargetRegistry is an object adapter of llvm::TargetRegistry
+ */
class TargetRegistry
{
public:
@@ -161,7 +50,9 @@
/// this is done by initializing all targets at program startup.
///
/// @param T - The target being registered.
- static void RegisterTarget(mcld::Target &T);
+ static void RegisterTarget(Target& pTarget,
+ const char* pName,
+ Target::TripleMatchQualityFnTy pQualityFn);
/// RegisterTargetMachine - Register a TargetMachine implementation for the
/// given target.
@@ -221,16 +112,23 @@
T.DiagnosticLineInfoCtorFn = Fn;
}
- /// lookupTarget - Lookup a target based on a llvm::Target.
- ///
- /// @param T - The llvm::Target to find
- static const mcld::Target *lookupTarget(const llvm::Target& T);
-
- /// lookupTarget - function wrapper of llvm::TargetRegistry::lookupTarget
+ /// lookupTarget - Look up MCLinker target
///
/// @param Triple - The Triple string
/// @param Error - The returned error message
- static const mcld::Target *lookupTarget(const std::string &Triple,
+ static const mcld::Target *lookupTarget(const std::string& pTriple,
+ std::string& pError);
+
+ /// lookupTarget - Look up MCLinker target by an architecture name
+ /// and a triple. If the architecture name is not empty, then the
+ /// the lookup is done mainly by architecture. Otherwise, the target
+ /// triple is used.
+ ///
+ /// @param pArch - The architecture name
+ /// @param pTriple - The target triple
+ /// @param pError - The returned error message
+ static const mcld::Target *lookupTarget(const std::string& pArchName,
+ llvm::Triple& pTriple,
std::string &Error);
};
@@ -240,22 +138,27 @@
/// Target TheFooTarget; // The global target instance.
///
/// extern "C" void MCLDInitializeFooTargetInfo() {
-/// RegisterTarget X(TheFooTarget, "foo", "Foo description");
+/// RegisterTarget<llvm::Foo> X(TheFooTarget, "foo", "Foo description");
/// }
+template<llvm::Triple::ArchType TargetArchType = llvm::Triple::UnknownArch>
struct RegisterTarget
{
- RegisterTarget(mcld::Target &T, const char *Name) {
- llvm::TargetRegistry::iterator TIter, TEnd = llvm::TargetRegistry::end();
- // lookup llvm::Target
- for( TIter=llvm::TargetRegistry::begin(); TIter!=TEnd; ++TIter ) {
- if( 0==strcmp(TIter->getName(), Name) )
- break;
+public:
+ RegisterTarget(mcld::Target &pTarget, const char* pName) {
+ // if we've registered one, then return immediately.
+ TargetRegistry::iterator target, ie = TargetRegistry::end();
+ for (target = TargetRegistry::begin(); target != ie; ++target) {
+ if (0 == strcmp((*target)->name(), pName))
+ return;
}
- if (TIter != TEnd)
- T.setTarget(*TIter);
+ TargetRegistry::RegisterTarget(pTarget, pName, &getTripleMatchQuality);
+ }
- TargetRegistry::RegisterTarget(T);
+ static unsigned int getTripleMatchQuality(const llvm::Triple& pTriple) {
+ if (pTriple.getArch() == TargetArchType)
+ return 20;
+ return 0;
}
};
@@ -275,10 +178,11 @@
}
private:
- static mcld::MCLDTargetMachine *Allocator(const mcld::Target &T,
- llvm::TargetMachine& TM,
- const std::string &Triple) {
- return new TargetMachineImpl(TM, T, Triple);
+ static MCLDTargetMachine *Allocator(const llvm::Target& pLLVMTarget,
+ const mcld::Target& pMCLDTarget,
+ llvm::TargetMachine& pTM,
+ const std::string& pTriple) {
+ return new TargetMachineImpl(pTM, pLLVMTarget, pMCLDTarget, pTriple);
}
};
diff --git a/include/mcld/Support/TargetSelect.h b/include/mcld/Support/TargetSelect.h
index 7fcb74a..0b2be2a 100644
--- a/include/mcld/Support/TargetSelect.h
+++ b/include/mcld/Support/TargetSelect.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_SELECT_H
-#define MCLD_TARGET_SELECT_H
+#ifndef MCLD_SUPPORT_TARGETSELECT_H
+#define MCLD_SUPPORT_TARGETSELECT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/ToolOutputFile.h b/include/mcld/Support/ToolOutputFile.h
index 4dfc4e6..f1186c3 100644
--- a/include/mcld/Support/ToolOutputFile.h
+++ b/include/mcld/Support/ToolOutputFile.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_SUPPORT_TOOL_OUTPUT_FILE_H
-#define MCLD_SUPPORT_TOOL_OUTPUT_FILE_H
+#ifndef MCLD_SUPPORT_TOOLOUTPUTFILE_H
+#define MCLD_SUPPORT_TOOLOUTPUTFILE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -23,12 +23,9 @@
class Path;
class FileHandle;
-class MemoryArea;
-class raw_mem_ostream;
/** \class ToolOutputFile
- * \brief ToolOutputFile contains a raw_mem_ostream and adds extra new
- * features:
+ * \brief ToolOutputFile has the following features:
* - The file is automatically deleted if the process is killed.
* - The file is automatically deleted when the TooOutputFile object is
* destoryed unless the client calls keep().
@@ -36,21 +33,21 @@
class ToolOutputFile
{
public:
- ToolOutputFile(const std::string& pPath,
+ ToolOutputFile(const sys::fs::Path& pPath,
FileHandle::OpenMode pMode,
FileHandle::Permission pPermission);
~ToolOutputFile();
- /// mem_os - Return the contained raw_mem_ostream.
- raw_mem_ostream &mem_os();
+ /// fd - Retutn the output file handle
+ FileHandle& fd() { return m_FileHandle; }
- /// os - Return the contained formatted_raw_ostream
+ /// os - Return the contained raw_fd_ostream
+ llvm::raw_fd_ostream& os();
+
+ /// formatted_os - Return the contained formatted_raw_ostream
llvm::formatted_raw_ostream& formatted_os();
- /// memory - Return the contained MemoryArea.
- MemoryArea& memory();
-
/// keep - Indicate that the tool's job wrt this output file has been
/// successful and the file should not be deleted.
void keep();
@@ -59,7 +56,7 @@
class CleanupInstaller
{
public:
- explicit CleanupInstaller(const std::string& pPath);
+ explicit CleanupInstaller(const sys::fs::Path& pPath);
~CleanupInstaller();
@@ -67,19 +64,16 @@
bool Keep;
private:
- std::string m_Path;
+ sys::fs::Path m_Path;
};
private:
FileHandle m_FileHandle;
CleanupInstaller m_Installer;
- MemoryArea* m_pMemoryArea;
- raw_mem_ostream* m_pOStream;
- llvm::formatted_raw_ostream* m_pFOStream;
-
+ llvm::raw_fd_ostream* m_pFdOstream;
+ llvm::formatted_raw_ostream* m_pFormattedOstream;
};
} // namespace of mcld
#endif
-
diff --git a/include/mcld/Support/UniqueGCFactory.h b/include/mcld/Support/UniqueGCFactory.h
index 3147bab..73c1110 100644
--- a/include/mcld/Support/UniqueGCFactory.h
+++ b/include/mcld/Support/UniqueGCFactory.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_UNIQUE_GCFACTORY_H
-#define MCLD_UNIQUE_GCFACTORY_H
+#ifndef MCLD_SUPPORT_UNIQUEGCFACTORY_H
+#define MCLD_SUPPORT_UNIQUEGCFACTORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Support/raw_mem_ostream.h b/include/mcld/Support/raw_mem_ostream.h
deleted file mode 100644
index b2db64a..0000000
--- a/include/mcld/Support/raw_mem_ostream.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//===- raw_mem_ostream.h --------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_RAW_MEMORY_AREA_OSTREAM_H
-#define MCLD_RAW_MEMORY_AREA_OSTREAM_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <string>
-
-#include <llvm/Support/raw_ostream.h>
-
-namespace mcld {
-
-class MemoryArea;
-
-class raw_mem_ostream : public llvm::raw_ostream
-{
-public:
- /// constructor - pMemoryArea must be writable.
- explicit raw_mem_ostream(MemoryArea &pMemoryArea);
-
- ~raw_mem_ostream();
-
- MemoryArea& getMemoryArea() {
- flush();
- return m_MemoryArea;
- }
-
-private:
- /// write_impl - See raw_ostream::write_impl.
- virtual void write_impl(const char *pPtr, size_t pSize);
-
- /// current_pos - Return the current position within the stream, not
- /// counting the bytes currently in the buffer.
- virtual uint64_t current_pos() const;
-
-private:
- MemoryArea& m_MemoryArea;
- uint64_t m_Position;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Support/raw_ostream.h b/include/mcld/Support/raw_ostream.h
index 0e2cc40..6274e49 100644
--- a/include/mcld/Support/raw_ostream.h
+++ b/include/mcld/Support/raw_ostream.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_RAW_OSTREAM_H
-#define MCLD_RAW_OSTREAM_H
+#ifndef MCLD_SUPPORT_RAWOSTREAM_H
+#define MCLD_SUPPORT_RAWOSTREAM_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Target/DarwinLDBackend.h b/include/mcld/Target/DarwinLDBackend.h
index d55055a..9003812 100644
--- a/include/mcld/Target/DarwinLDBackend.h
+++ b/include/mcld/Target/DarwinLDBackend.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef DARWINLDBACKEND_H
-#define DARWINLDBACKEND_H
+#ifndef MCLD_TARGET_DARWINLDBACKEND_H
+#define MCLD_TARGET_DARWINLDBACKEND_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Target/ELFAttribute.h b/include/mcld/Target/ELFAttribute.h
new file mode 100644
index 0000000..7d9d30d
--- /dev/null
+++ b/include/mcld/Target/ELFAttribute.h
@@ -0,0 +1,125 @@
+//===- ELFAttribute.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_ELFATTRIBUTE_H
+#define MCLD_TARGET_ELFATTRIBUTE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Target/ELFAttributeData.h>
+
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/ADT/StringRef.h>
+
+namespace mcld {
+
+class ELFAttributeData;
+class GNULDBackend;
+class Input;
+class LDSection;
+class LinkerConfig;
+
+/** \class ELFAttribute
+ * \brief ELFAttribute is the attribute section in an ELF file.
+ */
+class ELFAttribute
+{
+public:
+ // ARM [ABI-addenda], 2.2.3.
+ static const char FormatVersion = 'A';
+ static const size_t FormatVersionFieldSize = sizeof(FormatVersion); // a byte
+ static const size_t SubsectionLengthFieldSize = 4; // a 4-byte integer
+
+ // MinimalELFAttributeSubsectionSize is the minimal number of bytes a valid
+ // subsection in ELF attribute section should have.
+ static const size_t MinimalELFAttributeSubsectionSize
+ = 1 /* Tag_File, see ARM [ABI-addenda], 2.2.4 */ +
+ 4 /* byte-size, see ARM [ABI-addenda], 2.2.4 */;
+
+ // MinimalELFAttributeSectionSize is the minimal number of bytes a valid ELF
+ // attribute section should have.
+ static const size_t MinimalELFAttributeSectionSize
+ = FormatVersionFieldSize + SubsectionLengthFieldSize +
+ 2 /* vendor-name, a char plus '\0', see ARM [ABI-addenda], 2.2.3 */ +
+ 1 * MinimalELFAttributeSubsectionSize;
+
+public:
+ ELFAttribute(const GNULDBackend &pBackend, const LinkerConfig& pConfig)
+ : m_Backend(pBackend), m_Config(pConfig) { }
+
+ ~ELFAttribute();
+
+public:
+ /// merge - merge attributes from input (attribute) section
+ bool merge(const Input &pInput, LDSection &pInputAttrSectHdr);
+
+ /// sizeOutput - calculate the number of bytes required to encode this
+ /// attribute data section
+ size_t sizeOutput() const;
+
+ /// emit - encode and write out this attribute section
+ size_t emit(MemoryRegion &pRegion) const;
+
+ inline const GNULDBackend &backend() const { return m_Backend; }
+
+ inline const LinkerConfig &config() const { return m_Config; }
+
+ // Place vendor's attribute data under the management.
+ void registerAttributeData(ELFAttributeData& pAttrData);
+
+private:
+ /** \class Subsection
+ * \brief A helper class to wrap ELFAttributeData and to provide general
+ * interfaces for ELFAttribute to operate on
+ */
+ class Subsection {
+ public:
+ Subsection(ELFAttribute &pParent, ELFAttributeData &pAttrData)
+ : m_Parent(pParent), m_AttrData(pAttrData) { }
+
+ public:
+ bool isMyAttribute(llvm::StringRef pVendorName) const
+ {
+ return (m_AttrData.getVendorName() == pVendorName);
+ }
+
+ /// merge - Merge the attributes from the section in the input data.
+ bool merge(const Input &pInput, ConstAddress pData, size_t pSize);
+
+ /// sizeOutput - calculate the number of bytes required to encode this
+ /// subsection
+ size_t sizeOutput() const;
+
+ /// emit - write out this attribute subsection to the buffer.
+ size_t emit(char *pBuf) const;
+
+ private:
+ // The attribute section this subsection belongs to
+ ELFAttribute &m_Parent;
+
+ // The attribute data containing in this subsection
+ ELFAttributeData &m_AttrData;
+ };
+
+ // Obtain the corresponding subsection of the specified vendor
+ Subsection *getSubsection(llvm::StringRef pVendorName) const;
+
+private:
+ const GNULDBackend &m_Backend;
+
+ const LinkerConfig &m_Config;
+
+ // There is at most two subsections ("aeabi" and "gnu") in most cases.
+ llvm::SmallVector<Subsection*, 2> m_Subsections;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Target/ELFAttributeData.h b/include/mcld/Target/ELFAttributeData.h
new file mode 100644
index 0000000..1cb9ad7
--- /dev/null
+++ b/include/mcld/Target/ELFAttributeData.h
@@ -0,0 +1,114 @@
+//===- ELFAttributeData.h -------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_ELFATTRIBUTEDATA_H
+#define MCLD_TARGET_ELFATTRIBUTEDATA_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <stdint.h>
+#include <string>
+#include <utility>
+
+namespace mcld {
+
+class ELFAttributeValue;
+class Input;
+class LinkerConfig;
+
+/** \class ELFAttributeData
+ * \brief ELFAttributeData handles data in vendor attribute subsection.
+ */
+class ELFAttributeData
+{
+public:
+ typedef uint32_t TagType;
+
+ // Generic attribute tags shared between all vendors
+ enum {
+ Tag_NULL = 0,
+ Tag_File = 1,
+ Tag_Section = 2,
+ Tag_Symbol = 3,
+ };
+
+public:
+ ELFAttributeData(const char* pVendor) : m_Vendor(pVendor) { }
+
+ virtual ~ELFAttributeData() { }
+
+public:
+ inline const std::string &getVendorName() const { return m_Vendor; }
+
+ /// getAttributeValue - query the data store for the attribute value of the
+ /// given tag.
+ virtual const ELFAttributeValue *getAttributeValue(TagType pTag) const = 0;
+
+ /// getOrCreateAttributeValue - obtain attribute value for the given tag and
+ /// create if it does not exist.
+ ///
+ /// It returns a pair containing the attribute value instance (guaranteed to
+ /// be non-NULL) and a boolean value indicating whether the instance is newly
+ /// created (true) or not (false.)
+ virtual std::pair<ELFAttributeValue*, bool>
+ getOrCreateAttributeValue(TagType pTag) = 0;
+
+ /// preMerge - hooks to call before starting merge the attribute data in an
+ /// input.
+ virtual bool preMerge(const Input &pInput) { return true; }
+
+ /// merge - implement logics to merge input attribute to the output.
+ virtual bool merge(const LinkerConfig& pConfig, const Input &pInput,
+ TagType pTag, const ELFAttributeValue& pInAttr) = 0;
+
+ /// postMerge - hooks to call after finishing merge the attribute data from an
+ /// input.
+ virtual bool postMerge(const LinkerConfig& pConfig, const Input &pInput)
+ { return true; }
+
+ /// sizeOutput - obtain number of bytes required to encode the attribute data.
+ virtual size_t sizeOutput() const = 0;
+
+ /// emit - write out attribute data to the buffer and return the number of
+ /// bytes written
+ virtual size_t emit(char *pBuf) const = 0;
+
+public:
+ /// ReadTag - read an attribute tag from input buffer.
+ ///
+ /// If the read succeeds, pBuf moves to the new position just pass the end of
+ /// the tag in the buffer and pBufSize decreases the size of tag in the
+ /// buffer. Otherwise, this function will return false and change nothing
+ /// except leaving undefined value in pTag.
+ static bool ReadTag(TagType& pTag, const char* &pBuf, size_t &pBufSize);
+
+ /// ReadValue - read an attribute value from input buffer
+ ///
+ /// Similar with ReadTag() while this reads attribute value from the input
+ /// buffer. Note that the value type of the attribute must be properly set in
+ /// pValue prior the call.
+ static bool ReadValue(ELFAttributeValue& pValue, const char* &pBuf,
+ size_t &pBufSize);
+
+ /// WriteAttribute - write an attribute tag plus value to buffer.
+ ///
+ /// On success, the pBuf moves to the new position just pass the end of the
+ /// attribute data just written. Otherwise, it returns false and leaves pBuf
+ /// in an undefined position. Note that buffer is guaranteed to be able to
+ /// contain the attribute data.
+ static bool WriteAttribute(TagType pTag, const ELFAttributeValue& pValue,
+ char* &pBuf);
+
+private:
+ const std::string m_Vendor;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Target/ELFAttributeValue.h b/include/mcld/Target/ELFAttributeValue.h
new file mode 100644
index 0000000..0af3c97
--- /dev/null
+++ b/include/mcld/Target/ELFAttributeValue.h
@@ -0,0 +1,125 @@
+//===- ELFAttributeValue.h ------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_ELFATTRIBUTEVALUE_H
+#define MCLD_TARGET_ELFATTRIBUTEVALUE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <string>
+
+namespace mcld
+{
+
+/** \class ELFAttributeValue
+ * \brief ELFAttributeValue stroes the value of an attribute tag. The attribtue
+ * tag itself is not stored in this object.
+ */
+class ELFAttributeValue
+{
+public:
+ // Type of value that an attribute tag holds.
+ enum Type {
+ // The value contains no data and has unknown type.
+ Uninitialized = 0,
+
+ // The value contains integer data.
+ Int = 1L << 0,
+
+ // The value contains string data.
+ String = 1L << 1,
+
+ // This is for attribute in which "default value" (0 for int type and empty
+ // string for string type) has special meaning for them. That is, the
+ // default value is "disabled" and meaningful for those attribute.
+ NoDefault = 1L << 2,
+ };
+
+public:
+ ELFAttributeValue()
+ : m_Type(Uninitialized), m_IntValue(0), m_StringValue() { }
+
+ ~ELFAttributeValue() { }
+
+public:
+ unsigned int type() const
+ { return m_Type; }
+
+ void setType(unsigned int pType)
+ { m_Type = pType; }
+
+ unsigned int getIntValue() const
+ { return m_IntValue; }
+
+ void setIntValue(unsigned int pIntValue)
+ { m_IntValue = pIntValue; }
+
+ const std::string &getStringValue() const
+ { return m_StringValue; }
+
+ void setStringValue(const std::string &pStringValue)
+ { m_StringValue = pStringValue; }
+
+ void setStringValue(const char *pStringValue, size_t pSize)
+ { m_StringValue.assign(pStringValue, pSize); }
+
+ void setStringValue(const char *pStringValue)
+ { m_StringValue.assign(pStringValue); }
+
+ size_t getSize() const;
+
+ inline bool isUninitialized() const
+ { return (m_Type == Uninitialized); }
+
+ inline bool isInitialized() const
+ { return !isUninitialized(); }
+
+ inline bool isIntValue() const
+ { return (m_Type & Int); }
+
+ inline bool isStringValue() const
+ { return (m_Type & String); }
+
+ inline bool hasNoDefault() const
+ { return (m_Type & NoDefault); }
+
+ bool isDefaultValue() const;
+
+ // Returns true if this attribute value should be emitted to the output.
+ inline bool shouldEmit() const {
+ // Attribute with non-default value should be emitted.
+ return !isDefaultValue();
+ }
+
+ bool equals(const ELFAttributeValue& pValue) const;
+
+ bool operator==(const ELFAttributeValue& pValue) const
+ { return equals(pValue); }
+ bool operator!=(const ELFAttributeValue& pValue) const
+ { return !equals(pValue); }
+
+ /// reset - reset this value to the uninitialized state
+ void reset()
+ {
+ m_Type = Uninitialized;
+ m_IntValue = 0;
+ m_StringValue.clear();
+ return;
+ }
+
+private:
+ unsigned int m_Type;
+
+ unsigned int m_IntValue;
+ std::string m_StringValue;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/Target/ELFDynamic.h b/include/mcld/Target/ELFDynamic.h
index 62f534d..c9b257f 100644
--- a/include/mcld/Target/ELFDynamic.h
+++ b/include/mcld/Target/ELFDynamic.h
@@ -6,14 +6,15 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_DYNAMIC_SECTION_H
-#define MCLD_ELF_DYNAMIC_SECTION_H
+#ifndef MCLD_TARGET_ELFDYNAMIC_H
+#define MCLD_TARGET_ELFDYNAMIC_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <llvm/Support/ELF.h>
#include <mcld/LD/LDSection.h>
+#include <mcld/Support/FileOutputBuffer.h>
+#include <llvm/Support/ELF.h>
#include <vector>
#include <cstring>
@@ -22,7 +23,6 @@
class ELFFileFormat;
class GNULDBackend;
class LinkerConfig;
-class MemoryRegion;
namespace elf_dynamic {
diff --git a/include/mcld/Target/ELFEmulation.h b/include/mcld/Target/ELFEmulation.h
index 9d35792..2a79f11 100644
--- a/include/mcld/Target/ELFEmulation.h
+++ b/include/mcld/Target/ELFEmulation.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_EMULATION_H
-#define MCLD_ELF_EMULATION_H
+#ifndef MCLD_TARGET_ELFEMULATION_H
+#define MCLD_TARGET_ELFEMULATION_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
diff --git a/include/mcld/Target/ELFMCLinker.h b/include/mcld/Target/ELFMCLinker.h
index 76f46e8..2cead3b 100644
--- a/include/mcld/Target/ELFMCLinker.h
+++ b/include/mcld/Target/ELFMCLinker.h
@@ -11,8 +11,8 @@
// This pass set up default parameters for ELF.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_ELF_SECTION_LINKER_H
-#define MCLD_ELF_SECTION_LINKER_H
+#ifndef MCLD_TARGET_ELFMCLINKER_H
+#define MCLD_TARGET_ELFMCLINKER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -22,13 +22,14 @@
class Module;
class Output;
+class FileHandle;
class ELFMCLinker : public MCLinker
{
public:
ELFMCLinker(LinkerConfig& pConfig,
mcld::Module& pModule,
- MemoryArea& pOutput);
+ FileHandle& pFileHandle);
virtual ~ELFMCLinker();
};
diff --git a/include/mcld/Target/GNUInfo.h b/include/mcld/Target/GNUInfo.h
index 86a29ba..247d817 100644
--- a/include/mcld/Target/GNUInfo.h
+++ b/include/mcld/Target/GNUInfo.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_GNU_INFO_H
-#define MCLD_TARGET_GNU_INFO_H
+#ifndef MCLD_TARGET_GNUINFO_H
+#define MCLD_TARGET_GNUINFO_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -36,7 +36,7 @@
uint8_t OSABI() const;
/// ABIVersion - the value of e_ident[EI_ABIVRESION]
- uint8_t ABIVersion() const { return 0x0; }
+ virtual uint8_t ABIVersion() const { return 0x0; }
/// defaultTextSegmentAddr - target should specify its own default start address
/// of the text segment. esp. for exec.
@@ -65,7 +65,7 @@
/// here. If target favors the different size, please override this function
virtual uint64_t abiPageSize() const { return 0x1000; }
-private:
+protected:
const llvm::Triple& m_Triple;
};
diff --git a/include/mcld/Target/GNULDBackend.h b/include/mcld/Target/GNULDBackend.h
index 3384eae..0d23964 100644
--- a/include/mcld/Target/GNULDBackend.h
+++ b/include/mcld/Target/GNULDBackend.h
@@ -6,31 +6,21 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_GNU_LDBACKEND_H
-#define MCLD_TARGET_GNU_LDBACKEND_H
+#ifndef MCLD_TARGET_GNULDBACKEND_H
+#define MCLD_TARGET_GNULDBACKEND_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <mcld/Target/TargetLDBackend.h>
-#include <llvm/Support/ELF.h>
-#include <mcld/ADT/HashTable.h>
-#include <mcld/ADT/HashEntry.h>
-#include <mcld/LD/ELFDynObjFileFormat.h>
-#include <mcld/LD/ELFExecFileFormat.h>
-#include <mcld/LD/ELFObjectFileFormat.h>
+#include <mcld/Module.h>
#include <mcld/LD/GNUArchiveReader.h>
-#include <mcld/LD/ELFObjectReader.h>
#include <mcld/LD/ELFDynObjReader.h>
#include <mcld/LD/ELFBinaryReader.h>
+#include <mcld/LD/ELFObjectReader.h>
#include <mcld/LD/ELFObjectWriter.h>
-#include <mcld/LD/ELFSegment.h>
-#include <mcld/LD/ELFSegmentFactory.h>
-#include <mcld/Target/ELFDynamic.h>
-#include <mcld/Target/GNUInfo.h>
-#include <mcld/Support/GCFactory.h>
-#include <mcld/Module.h>
+#include <llvm/Support/ELF.h>
namespace mcld {
@@ -42,6 +32,15 @@
class BranchIslandFactory;
class StubFactory;
class GNUInfo;
+class ELFFileFormat;
+class ELFSegmentFactory;
+class ELFAttribute;
+class ELFDynamic;
+class ELFDynObjFileFormat;
+class ELFExecFileFormat;
+class ELFObjectFileFormat;
+class LinkerScript;
+class Relocation;
/** \class GNULDBackend
* \brief GNULDBackend provides a common interface for all GNU Unix-OS
@@ -110,6 +109,9 @@
/// getSegmentStartAddr - this function returns the start address of the segment
uint64_t getSegmentStartAddr(const LinkerScript& pScript) const;
+ /// sizeShstrtab - compute the size of .shstrtab
+ void sizeShstrtab(Module& pModule);
+
/// sizeNamePools - compute the size of regular name pools
/// In ELF executable files, regular name pools are .symtab, .strtab.,
/// .dynsym, .dynstr, and .hash
@@ -120,25 +122,25 @@
MemoryRegion& pRegion) const = 0;
/// emitRegNamePools - emit regular name pools - .symtab, .strtab
- virtual void emitRegNamePools(const Module& pModule, MemoryArea& pOutput);
+ virtual void emitRegNamePools(const Module& pModule, FileOutputBuffer& pOutput);
/// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
- virtual void emitDynNamePools(Module& pModule, MemoryArea& pOutput);
+ virtual void emitDynNamePools(Module& pModule, FileOutputBuffer& pOutput);
/// emitELFHashTab - emit .hash
virtual void emitELFHashTab(const Module::SymbolTable& pSymtab,
- MemoryArea& pOutput);
+ FileOutputBuffer& pOutput);
/// emitGNUHashTab - emit .gnu.hash
virtual void emitGNUHashTab(Module::SymbolTable& pSymtab,
- MemoryArea& pOutput);
+ FileOutputBuffer& pOutput);
/// sizeInterp - compute the size of program interpreter's name
/// In ELF executables, this is the length of dynamic linker's path name
virtual void sizeInterp();
/// emitInterp - emit the .interp
- virtual void emitInterp(MemoryArea& pOutput);
+ virtual void emitInterp(FileOutputBuffer& pOutput);
/// hasEntryInStrTab - symbol has an entry in a .strtab
virtual bool hasEntryInStrTab(const LDSymbol& pSym) const;
@@ -169,16 +171,11 @@
virtual unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const
{ return (unsigned int)-1; }
- /// numOfSegments - return the number of segments
- /// if the target favors other ways to emit program header, please override
- /// this function
- size_t numOfSegments() const { return m_ELFSegmentTable.size(); }
+ /// elfSegmentTable - return the reference of the elf segment table
+ ELFSegmentFactory& elfSegmentTable();
/// elfSegmentTable - return the reference of the elf segment table
- ELFSegmentFactory& elfSegmentTable() { return m_ELFSegmentTable; }
-
- /// elfSegmentTable - return the reference of the elf segment table
- const ELFSegmentFactory& elfSegmentTable() const { return m_ELFSegmentTable; }
+ const ELFSegmentFactory& elfSegmentTable() const;
/// commonPageSize - the common page size of the target machine
uint64_t commonPageSize() const;
@@ -198,6 +195,58 @@
/// update the output section flags based on input section flags.
virtual bool updateSectionFlags(LDSection& pTo, const LDSection& pFrom);
+ /// readRelocation - read ELF32_Rel entry
+ virtual bool readRelocation(const llvm::ELF::Elf32_Rel& pRel,
+ uint32_t& pType,
+ uint32_t& pSymIdx,
+ uint32_t& pOffset) const;
+
+ /// readRelocation - read ELF32_Rela entry
+ virtual bool readRelocation(const llvm::ELF::Elf32_Rela& pRel,
+ uint32_t& pType,
+ uint32_t& pSymIdx,
+ uint32_t& pOffset,
+ int32_t& pAddend) const;
+
+ /// readRelocation - read ELF64_Rel entry
+ virtual bool readRelocation(const llvm::ELF::Elf64_Rel& pRel,
+ uint32_t& pType,
+ uint32_t& pSymIdx,
+ uint64_t& pOffset) const;
+
+ /// readRel - read ELF64_Rela entry
+ virtual bool readRelocation(const llvm::ELF::Elf64_Rela& pRel,
+ uint32_t& pType,
+ uint32_t& pSymIdx,
+ uint64_t& pOffset,
+ int64_t& pAddend) const;
+
+ /// emitRelocation - write data to the ELF32_Rel entry
+ virtual void emitRelocation(llvm::ELF::Elf32_Rel& pRel,
+ uint32_t pType,
+ uint32_t pSymIdx,
+ uint32_t pOffset) const;
+
+ /// emitRelocation - write data to the ELF32_Rela entry
+ virtual void emitRelocation(llvm::ELF::Elf32_Rela& pRel,
+ uint32_t pType,
+ uint32_t pSymIdx,
+ uint32_t pOffset,
+ int32_t pAddend) const;
+
+ /// emitRelocation - write data to the ELF64_Rel entry
+ virtual void emitRelocation(llvm::ELF::Elf64_Rel& pRel,
+ uint32_t pType,
+ uint32_t pSymIdx,
+ uint64_t pOffset) const;
+
+ /// emitRelocation - write data to the ELF64_Rela entry
+ virtual void emitRelocation(llvm::ELF::Elf64_Rela& pRel,
+ uint32_t pType,
+ uint32_t pSymIdx,
+ uint64_t pOffset,
+ int64_t pAddend) const;
+
/// symbolNeedsPLT - return whether the symbol needs a PLT entry
/// @ref Google gold linker, symtab.h:596
bool symbolNeedsPLT(const ResolveInfo& pSym) const;
@@ -223,11 +272,11 @@
/// isDynamicSymbol
/// @ref Google gold linker: symtab.cc:311
- bool isDynamicSymbol(const LDSymbol& pSymbol);
+ bool isDynamicSymbol(const LDSymbol& pSymbol) const;
/// isDynamicSymbol
/// @ref Google gold linker: symtab.cc:311
- bool isDynamicSymbol(const ResolveInfo& pResolveInfo);
+ bool isDynamicSymbol(const ResolveInfo& pResolveInfo) const;
virtual ResolveInfo::Desc getSymDesc(uint16_t pShndx) const {
return ResolveInfo::Define;
@@ -247,6 +296,9 @@
LDSymbol& getTBSSSymbol();
const LDSymbol& getTBSSSymbol() const;
+ /// getEntry - get the entry point name
+ llvm::StringRef getEntry(const Module& pModule) const;
+
// ----- relaxation ----- //
/// initBRIslandFactory - initialize the branch island factory for relaxation
bool initBRIslandFactory();
@@ -267,7 +319,27 @@
/// checkAndSetHasTextRel - check pSection flag to set HasTextRel
void checkAndSetHasTextRel(const LDSection& pSection);
+ /// sortRelocation - sort the dynamic relocations to let dynamic linker
+ /// process relocations more efficiently
+ void sortRelocation(LDSection& pSection);
+
+ /// createAndSizeEhFrameHdr - This is seperated since we may add eh_frame
+ /// entry in the middle
+ void createAndSizeEhFrameHdr(Module& pModule);
+
+ /// attribute - the attribute section data.
+ ELFAttribute& attribute() { return *m_pAttribute; }
+
+ /// attribute - the attribute section data.
+ const ELFAttribute& attribute() const { return *m_pAttribute; }
+
protected:
+ /// getRelEntrySize - the size in BYTE of rel type relocation
+ virtual size_t getRelEntrySize() = 0;
+
+ /// getRelEntrySize - the size in BYTE of rela type relocation
+ virtual size_t getRelaEntrySize() = 0;
+
uint64_t getSymbolSize(const LDSymbol& pSymbol) const;
uint64_t getSymbolInfo(const LDSymbol& pSymbol) const;
@@ -315,33 +387,19 @@
/// getSegmentFlag - give a section flag and return the corresponding segment
/// flag
- inline uint32_t getSegmentFlag(const uint32_t pSectionFlag)
- {
- uint32_t flag = llvm::ELF::PF_R;
- if (0 != (pSectionFlag & llvm::ELF::SHF_WRITE))
- flag |= llvm::ELF::PF_W;
- if (0 != (pSectionFlag & llvm::ELF::SHF_EXECINSTR))
- flag |= llvm::ELF::PF_X;
- return flag;
- }
+ inline uint32_t getSegmentFlag(const uint32_t pSectionFlag);
/// setupGNUStackInfo - setup the section flag of .note.GNU-stack in output
void setupGNUStackInfo(Module& pModule);
- /// setupRelro - setup the offset constraint of PT_RELRO
- void setupRelro(Module& pModule);
+ /// setOutputSectionOffset - helper function to set output sections' offset.
+ void setOutputSectionOffset(Module& pModule);
- /// setOutputSectionOffset - helper function to set a group of output sections'
- /// offset, and set pSectBegin to pStartOffset if pStartOffset is not -1U.
- void setOutputSectionOffset(Module& pModule,
- Module::iterator pSectBegin,
- Module::iterator pSectEnd,
- uint64_t pStartOffset = -1U);
+ /// setOutputSectionAddress - helper function to set output sections' address.
+ void setOutputSectionAddress(Module& pModule);
- /// setOutputSectionOffset - helper function to set output sections' address.
- void setOutputSectionAddress(Module& pModule,
- Module::iterator pSectBegin,
- Module::iterator pSectEnd);
+ /// placeOutputSections - place output sections based on SectionMap
+ void placeOutputSections(Module& pModule);
/// layout - layout method
void layout(Module& pModule);
@@ -359,7 +417,7 @@
virtual void doPostLayout(Module& pModule, IRBuilder& pLinker) = 0;
/// postProcessing - Backend can do any needed modification in the final stage
- void postProcessing(MemoryArea& pOutput);
+ void postProcessing(FileOutputBuffer& pOutput);
/// dynamic - the dynamic section of the target machine.
virtual ELFDynamic& dynamic() = 0;
@@ -380,56 +438,48 @@
virtual bool doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished)
{ return false; }
- /// getRelEntrySize - the size in BYTE of rel type relocation
- virtual size_t getRelEntrySize() = 0;
-
- /// getRelEntrySize - the size in BYTE of rela type relocation
- virtual size_t getRelaEntrySize() = 0;
-
protected:
// Based on Kind in LDFileFormat to define basic section orders for ELF, and
// refer gold linker to add more enumerations to handle Regular and BSS kind
enum SectionOrder {
- SHO_INTERP = 1, // .interp
- SHO_RO_NOTE, // .note.ABI-tag, .note.gnu.build-id
- SHO_NAMEPOOL, // *.hash, .dynsym, .dynstr
- SHO_RELOCATION, // .rel.*, .rela.*
- SHO_REL_PLT, // .rel.plt should come after other .rel.*
- SHO_INIT, // .init
- SHO_PLT, // .plt
- SHO_TEXT, // .text
- SHO_FINI, // .fini
- SHO_RO, // .rodata
- SHO_EXCEPTION, // .eh_frame_hdr, .eh_frame, .gcc_except_table
- SHO_TLS_DATA, // .tdata
- SHO_TLS_BSS, // .tbss
- SHO_RELRO_LOCAL, // .data.rel.ro.local
- SHO_RELRO, // .data.rel.ro,
- SHO_RELRO_LAST, // for x86 to adjust .got if needed
- SHO_NON_RELRO_FIRST, // for x86 to adjust .got.plt if needed
- SHO_DATA, // .data
- SHO_LARGE_DATA, // .ldata
- SHO_RW_NOTE, //
- SHO_SMALL_DATA, // .sdata
- SHO_SMALL_BSS, // .sbss
- SHO_BSS, // .bss
- SHO_LARGE_BSS, // .lbss
- SHO_UNDEFINED, // default order
- SHO_STRTAB // .strtab
+ SHO_NULL = 0, // NULL
+ SHO_INTERP, // .interp
+ SHO_RO_NOTE, // .note.ABI-tag, .note.gnu.build-id
+ SHO_NAMEPOOL, // *.hash, .dynsym, .dynstr
+ SHO_RELOCATION, // .rel.*, .rela.*
+ SHO_REL_PLT, // .rel.plt should come after other .rel.*
+ SHO_INIT, // .init
+ SHO_PLT, // .plt
+ SHO_TEXT, // .text
+ SHO_FINI, // .fini
+ SHO_RO, // .rodata
+ SHO_EXCEPTION, // .eh_frame_hdr, .eh_frame, .gcc_except_table
+ SHO_TLS_DATA, // .tdata
+ SHO_TLS_BSS, // .tbss
+ SHO_RELRO_LOCAL, // .data.rel.ro.local
+ SHO_RELRO, // .data.rel.ro,
+ SHO_RELRO_LAST, // for x86 to adjust .got if needed
+ SHO_NON_RELRO_FIRST, // for x86 to adjust .got.plt if needed
+ SHO_DATA, // .data
+ SHO_LARGE_DATA, // .ldata
+ SHO_RW_NOTE, //
+ SHO_SMALL_DATA, // .sdata
+ SHO_SMALL_BSS, // .sbss
+ SHO_BSS, // .bss
+ SHO_LARGE_BSS, // .lbss
+ SHO_UNDEFINED, // default order
+ SHO_STRTAB // .strtab
};
- typedef std::pair<LDSection*, unsigned int> SHOEntry;
-
- struct SHOCompare
+ // for -z combreloc
+ struct RelocCompare
{
- bool operator()(const SHOEntry& X, const SHOEntry& Y) const
- { return X.second < Y.second; }
- };
-
- struct SymCompare
- {
- bool operator()(const LDSymbol* X, const LDSymbol* Y) const
- { return (X==Y); }
+ RelocCompare(const GNULDBackend& pBackend)
+ : m_Backend(pBackend) {
+ }
+ bool operator()(const Relocation* X, const Relocation* Y) const;
+ private:
+ const GNULDBackend& m_Backend;
};
// for gnu style hash table
@@ -440,6 +490,12 @@
bool operator()(const LDSymbol* X, const LDSymbol* Y) const;
};
+ struct SymCompare
+ {
+ bool operator()(const LDSymbol* X, const LDSymbol* Y) const
+ { return (X==Y); }
+ };
+
struct SymPtrHash
{
size_t operator()(const LDSymbol* pKey) const
@@ -467,7 +523,7 @@
GNUInfo* m_pInfo;
// ELF segment factory
- ELFSegmentFactory m_ELFSegmentTable;
+ ELFSegmentFactory* m_pELFSegmentTable;
// branch island factory
BranchIslandFactory* m_pBRIslandFactory;
@@ -481,6 +537,9 @@
// section .eh_frame_hdr
EhFrameHdr* m_pEhFrameHdr;
+ // attribute section
+ ELFAttribute* m_pAttribute;
+
// ----- dynamic flags ----- //
// DF_TEXTREL of DT_FLAGS
bool m_bHasTextRel;
diff --git a/include/mcld/Target/GOT.h b/include/mcld/Target/GOT.h
index 9b61bcd..eb73741 100644
--- a/include/mcld/Target/GOT.h
+++ b/include/mcld/Target/GOT.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_GLOBAL_OFFSET_TABLE_H
-#define MCLD_GLOBAL_OFFSET_TABLE_H
+#ifndef MCLD_TARGET_GOT_H
+#define MCLD_TARGET_GOT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -80,13 +80,6 @@
// finalizeSectionSize - set LDSection size
virtual void finalizeSectionSize();
- /// reserve - reseve number of pNum of empty entries
- /// Before layout, we scan all relocations to determine if GOT entries are
- /// needed. If an entry is needed, the empty entry is reserved for layout
- /// to adjust the fragment offset. After that, we fill up the entries when
- /// applying relocations.
- virtual void reserve(size_t pNum = 1) = 0;
-
protected:
LDSection& m_Section;
SectionData* m_SectionData;
diff --git a/include/mcld/Target/KeyEntryMap.h b/include/mcld/Target/KeyEntryMap.h
new file mode 100644
index 0000000..8136687
--- /dev/null
+++ b/include/mcld/Target/KeyEntryMap.h
@@ -0,0 +1,204 @@
+//===- KeyEntryMap.h ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_TARGET_KEYENTRYMAP_H
+#define MCLD_TARGET_KEYENTRYMAP_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <vector>
+#include <list>
+
+namespace mcld {
+
+/** \class KeyEntryMap
+ * \brief KeyEntryMap is a <const KeyType*, ENTRY*> map.
+ */
+template<typename KEY, typename ENTRY>
+class KeyEntryMap
+{
+public:
+ typedef KEY KeyType;
+ typedef ENTRY EntryType;
+
+private:
+ struct EntryPair {
+ EntryPair(EntryType* pEntry1, EntryType* pEntry2)
+ : entry1(pEntry1), entry2(pEntry2)
+ {}
+
+ EntryType* entry1;
+ EntryType* entry2;
+ };
+
+ /// EntryOrPair - A key may mapping to a signal entry or a pair of entries,
+ /// user is responsible for the type of Mapping.entry
+ union EntryOrPair {
+ EntryType* entry_ptr;
+ EntryPair* pair_ptr;
+ };
+
+ struct Mapping {
+ const KeyType* key;
+ EntryOrPair entry;
+ };
+
+ typedef std::vector<Mapping> KeyEntryPool;
+ typedef std::list<EntryPair> PairListType;
+
+public:
+ typedef typename KeyEntryPool::iterator iterator;
+ typedef typename KeyEntryPool::const_iterator const_iterator;
+
+public:
+ /// lookUp - look up the entry mapping to pKey
+ const EntryType* lookUp(const KeyType& pKey) const;
+ EntryType* lookUp(const KeyType& pKey);
+
+ /// lookUpFirstEntry - look up the first entry mapping to pKey
+ const EntryType* lookUpFirstEntry(const KeyType& pKey) const;
+ EntryType* lookUpFirstEntry(const KeyType& pKey);
+
+ /// lookUpSecondEntry - look up the second entry mapping to pKey
+ const EntryType* lookUpSecondEntry(const KeyType& pKey) const;
+ EntryType* lookUpSecondEntry(const KeyType& pKey);
+
+ void record(const KeyType& pKey, EntryType& pEntry);
+ void record(const KeyType& pKey,
+ EntryType& pEntry1,
+ EntryType& pEntry2);
+
+ bool empty() const { return m_Pool.empty(); }
+ size_t size () const { return m_Pool.size(); }
+
+ const_iterator begin() const { return m_Pool.begin(); }
+ iterator begin() { return m_Pool.begin(); }
+ const_iterator end () const { return m_Pool.end(); }
+ iterator end () { return m_Pool.end(); }
+
+ void reserve(size_t pSize) { m_Pool.reserve(pSize); }
+
+private:
+ KeyEntryPool m_Pool;
+
+ /// m_Pairs - the EntryPairs
+ PairListType m_Pairs;
+};
+
+template<typename KeyType, typename EntryType>
+const EntryType*
+KeyEntryMap<KeyType, EntryType>::lookUp(const KeyType& pKey) const
+{
+ const_iterator mapping, mEnd = m_Pool.end();
+ for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
+ if (mapping->key == &pKey) {
+ return mapping->entry.entry_ptr;
+ }
+ }
+
+ return NULL;
+}
+
+template<typename KeyType, typename EntryType>
+EntryType*
+KeyEntryMap<KeyType, EntryType>::lookUp(const KeyType& pKey)
+{
+ iterator mapping, mEnd = m_Pool.end();
+ for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
+ if (mapping->key == &pKey) {
+ return mapping->entry.entry_ptr;
+ }
+ }
+
+ return NULL;
+}
+
+template<typename KeyType, typename EntryType>
+const EntryType*
+KeyEntryMap<KeyType, EntryType>::lookUpFirstEntry(const KeyType& pKey) const
+{
+ const_iterator mapping, mEnd = m_Pool.end();
+ for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
+ if (mapping->key == &pKey) {
+ return mapping->entry.pair_ptr->entry1;
+ }
+ }
+
+ return NULL;
+}
+
+template<typename KeyType, typename EntryType>
+EntryType*
+KeyEntryMap<KeyType, EntryType>::lookUpFirstEntry(const KeyType& pKey)
+{
+ const_iterator mapping, mEnd = m_Pool.end();
+ for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
+ if (mapping->key == &pKey) {
+ return mapping->entry.pair_ptr->entry1;
+ }
+ }
+
+ return NULL;
+}
+
+template<typename KeyType, typename EntryType>
+const EntryType*
+KeyEntryMap<KeyType, EntryType>::lookUpSecondEntry(const KeyType& pKey) const
+{
+ const_iterator mapping, mEnd = m_Pool.end();
+ for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
+ if (mapping->key == &pKey) {
+ return mapping->entry.pair_ptr->entry2;
+ }
+ }
+
+ return NULL;
+}
+
+template<typename KeyType, typename EntryType>
+EntryType*
+KeyEntryMap<KeyType, EntryType>::lookUpSecondEntry(const KeyType& pKey)
+{
+ const_iterator mapping, mEnd = m_Pool.end();
+ for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
+ if (mapping->key == &pKey) {
+ return mapping->entry.pair_ptr->entry2;
+ }
+ }
+
+ return NULL;
+}
+
+template<typename KeyType, typename EntryType>
+void
+KeyEntryMap<KeyType, EntryType>::record(const KeyType& pKey, EntryType& pEntry)
+{
+ Mapping mapping;
+ mapping.key = &pKey;
+ mapping.entry.entry_ptr = &pEntry;
+ m_Pool.push_back(mapping);
+}
+
+template<typename KeyType, typename EntryType>
+void
+KeyEntryMap<KeyType, EntryType>::record(const KeyType& pKey,
+ EntryType& pEntry1,
+ EntryType& pEntry2)
+{
+ Mapping mapping;
+ mapping.key = &pKey;
+ m_Pairs.push_back(EntryPair(&pEntry1, &pEntry2));
+ mapping.entry.pair_ptr = &m_Pairs.back();
+ m_Pool.push_back(mapping);
+}
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Target/OutputRelocSection.h b/include/mcld/Target/OutputRelocSection.h
index b0f8f2d..a109843 100644
--- a/include/mcld/Target/OutputRelocSection.h
+++ b/include/mcld/Target/OutputRelocSection.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_OUTPUT_RELOCATION_SECTION_H
-#define MCLD_OUTPUT_RELOCATION_SECTION_H
+#ifndef MCLD_TARGET_OUTPUTRELOCSECTION_H
+#define MCLD_TARGET_OUTPUTRELOCSECTION_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -32,6 +32,9 @@
~OutputRelocSection();
+ /// create - create an dynamic relocation entry
+ Relocation* create();
+
void reserveEntry(size_t pNum=1);
Relocation* consumeEntry();
diff --git a/include/mcld/Target/PLT.h b/include/mcld/Target/PLT.h
index 5d91446..7305a74 100644
--- a/include/mcld/Target/PLT.h
+++ b/include/mcld/Target/PLT.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_PROCEDURE_LINKAGE_TABLE_H
-#define MCLD_PROCEDURE_LINKAGE_TABLE_H
+#ifndef MCLD_TARGET_PLT_H
+#define MCLD_TARGET_PLT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -22,7 +22,7 @@
class ResolveInfo;
/** \class PLTEntryDefaultBase
- * \brief PLTEntryDefaultBase provides the default interface for PLE Entry
+ * \brief PLTEntryDefaultBase provides the default interface for PLT Entry
*/
class PLTEntryBase : public TargetFragment
{
@@ -33,7 +33,7 @@
virtual ~PLTEntryBase()
{
- delete m_pValue;
+ free(m_pValue);
}
void setValue(unsigned char* pValue)
@@ -81,10 +81,6 @@
virtual ~PLT();
- /// reserveEntry - reseve the number of pNum of empty entries
- /// The empty entris are reserved for layout to adjust the fragment offset.
- virtual void reserveEntry(size_t pNum = 1) = 0;
-
// finalizeSectionSize - set LDSection size
virtual void finalizeSectionSize() = 0;
diff --git a/include/mcld/Target/SymbolEntryMap.h b/include/mcld/Target/SymbolEntryMap.h
deleted file mode 100644
index fc5ea93..0000000
--- a/include/mcld/Target/SymbolEntryMap.h
+++ /dev/null
@@ -1,104 +0,0 @@
-//===- SymbolEntryMap.h ---------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_SYMBOL_ENTRY_MAP_H
-#define MCLD_TARGET_SYMBOL_ENTRY_MAP_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <vector>
-
-namespace mcld {
-
-class ResolveInfo;
-
-/** \class SymbolEntryMap
- * \brief SymbolEntryMap is a <const ResolveInfo*, ENTRY*> map.
- */
-template<typename ENTRY>
-class SymbolEntryMap
-{
-public:
- typedef ENTRY EntryType;
-
-private:
- struct Mapping {
- const ResolveInfo* symbol;
- EntryType* entry;
- };
-
- typedef std::vector<Mapping> SymbolEntryPool;
-
-public:
- typedef typename SymbolEntryPool::iterator iterator;
- typedef typename SymbolEntryPool::const_iterator const_iterator;
-
-public:
- const EntryType* lookUp(const ResolveInfo& pSymbol) const;
- EntryType* lookUp(const ResolveInfo& pSymbol);
-
- void record(const ResolveInfo& pSymbol, EntryType& pEntry);
-
- bool empty() const { return m_Pool.empty(); }
- size_t size () const { return m_Pool.size(); }
-
- const_iterator begin() const { return m_Pool.begin(); }
- iterator begin() { return m_Pool.begin(); }
- const_iterator end () const { return m_Pool.end(); }
- iterator end () { return m_Pool.end(); }
-
- void reserve(size_t pSize) { m_Pool.reserve(pSize); }
-
-private:
- SymbolEntryPool m_Pool;
-
-};
-
-template<typename EntryType>
-const EntryType*
-SymbolEntryMap<EntryType>::lookUp(const ResolveInfo& pSymbol) const
-{
- const_iterator mapping, mEnd = m_Pool.end();
- for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
- if (mapping->symbol == &pSymbol) {
- return mapping->entry;
- }
- }
-
- return NULL;
-}
-
-template<typename EntryType>
-EntryType*
-SymbolEntryMap<EntryType>::lookUp(const ResolveInfo& pSymbol)
-{
- iterator mapping, mEnd = m_Pool.end();
- for (mapping = m_Pool.begin(); mapping != mEnd; ++mapping) {
- if (mapping->symbol == &pSymbol) {
- return mapping->entry;
- }
- }
-
- return NULL;
-}
-
-template<typename EntryType>
-void
-SymbolEntryMap<EntryType>::record(const ResolveInfo& pSymbol, EntryType& pEntry)
-{
- Mapping mapping;
- mapping.symbol = &pSymbol;
- mapping.entry = &pEntry;
- m_Pool.push_back(mapping);
-}
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Target/TargetLDBackend.h b/include/mcld/Target/TargetLDBackend.h
index d3f14b2..29fb395 100644
--- a/include/mcld/Target/TargetLDBackend.h
+++ b/include/mcld/Target/TargetLDBackend.h
@@ -1,4 +1,4 @@
-//===-- llvm/Target/TargetLDBackend.h - Target LD Backend -----*- C++ -*-===//
+//===-- TargetLDBackend.h - Target LD Backend -------------------*- C++ -*-===//
//
// The MCLinker Project
//
@@ -9,36 +9,34 @@
#ifndef MCLD_TARGET_TARGETLDBACKEND_H
#define MCLD_TARGET_TARGETLDBACKEND_H
+#include <llvm/ADT/StringRef.h>
#include <llvm/Support/DataTypes.h>
+#include <mcld/LD/GarbageCollection.h>
namespace mcld {
-class Module;
-class LinkerConfig;
-class IRBuilder;
-class Relocation;
-class RelocationFactory;
-class Relocator;
-class Layout;
class ArchiveReader;
-class ObjectReader;
-class DynObjReader;
class BinaryReader;
-class ObjectWriter;
+class BinaryWriter;
+class BranchIslandFactory;
+class DynObjReader;
class DynObjWriter;
class ExecWriter;
-class BinaryWriter;
-class LDFileFormat;
-class LDSymbol;
-class LDSection;
-class SectionData;
+class FileOutputBuffer;
+class SectionReachedListMap;
+class IRBuilder;
class Input;
-class GOT;
-class MemoryArea;
-class MemoryAreaFactory;
-class BranchIslandFactory;
-class StubFactory;
+class LDSection;
+class LDSymbol;
+class Layout;
+class LinkerConfig;
+class Module;
class ObjectBuilder;
+class ObjectReader;
+class ObjectWriter;
+class Relocator;
+class SectionData;
+class StubFactory;
//===----------------------------------------------------------------------===//
/// TargetLDBackend - Generic interface to target specific assembler backends.
@@ -84,7 +82,7 @@
virtual void postLayout(Module& pModule, IRBuilder& pBuilder) = 0;
/// postProcessing - Backend can do any needed modification in the final stage
- virtual void postProcessing(MemoryArea& pOutput) = 0;
+ virtual void postProcessing(FileOutputBuffer& pOutput) = 0;
/// section start offset in the output file
virtual size_t sectionStartOffset() const = 0;
@@ -112,9 +110,17 @@
virtual bool allocateCommonSymbols(Module& pModule) = 0;
/// mergeSection - merge target dependent sections.
- virtual bool mergeSection(Module& pModule, LDSection& pInputSection)
+ virtual bool mergeSection(Module& pModule,
+ const Input& pInputFile,
+ LDSection& pInputSection)
{ return true; }
+ /// setUpReachedSectionsForGC - set the reference between two sections for
+ /// some special target sections. GC will set up the reference for the Regular
+ /// and BSS sections. Backends can also set up the reference if need.
+ virtual void setUpReachedSectionsForGC(const Module& pModule,
+ GarbageCollection::SectionReachedListMap& pSectReachedListMap) const { }
+
/// updateSectionFlags - update pTo's flags when merging pFrom
/// update the output section flags based on input section flags.
/// FIXME: (Luba) I know ELF need to merge flags, but I'm not sure if
@@ -130,6 +136,9 @@
/// In ELF executables, this is the length of dynamic linker's path name
virtual void sizeInterp() = 0;
+ /// getEntry - get the entry point name
+ virtual llvm::StringRef getEntry(const Module& pModule) const = 0;
+
// ----- relaxation ----- //
virtual bool initBRIslandFactory() = 0;
virtual bool initStubFactory() = 0;
@@ -144,6 +153,20 @@
/// mayRelax - return true if the backend needs to do relaxation
virtual bool mayRelax() = 0;
+ /// commonPageSize - the common page size of the target machine
+ virtual uint64_t commonPageSize() const = 0;
+
+ /// abiPageSize - the abi page size of the target machine
+ virtual uint64_t abiPageSize() const = 0;
+
+ /// sortRelocation - sort the dynamic relocations to let dynamic linker
+ /// process relocations more efficiently
+ virtual void sortRelocation(LDSection& pSection) = 0;
+
+ /// createAndSizeEhFrameHdr - This is seperated since we may add eh_frame
+ /// entry in the middle
+ virtual void createAndSizeEhFrameHdr(Module& pModule) = 0;
+
protected:
const LinkerConfig& config() const { return m_Config; }
diff --git a/include/mcld/TargetOptions.h b/include/mcld/TargetOptions.h
index dfdd773..5f7e339 100644
--- a/include/mcld/TargetOptions.h
+++ b/include/mcld/TargetOptions.h
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_OPTIONS_H
-#define MCLD_TARGET_OPTIONS_H
+#ifndef MCLD_TARGETOPTIONS_H
+#define MCLD_TARGETOPTIONS_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -44,6 +44,10 @@
void setTriple(const llvm::Triple& pTriple);
+ const std::string& getArch() const { return m_ArchName; }
+
+ void setArch(const std::string& pArchName);
+
const std::string& getTargetCPU() const { return m_TargetCPU; }
void setTargetCPU(const std::string& pCPU);
@@ -68,6 +72,7 @@
private:
llvm::Triple m_Triple;
+ std::string m_ArchName;
std::string m_TargetCPU;
std::string m_TargetFS;
Endian m_Endian;