MCLinker upstream commit 0459e386785c.
Change-Id: Ide6790f5a354b7fcc03d812d6c8cf43b1e309ba3
diff --git a/Android.mk b/Android.mk
index c094c8d..79c6d5b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -10,8 +10,11 @@
subdirs := \
lib/ADT \
lib/CodeGen \
+ lib/Core \
+ lib/Fragment \
lib/LD \
lib/MC \
+ lib/Object \
lib/Support \
lib/Target
diff --git a/include/mcld/ADT/Flags.h b/include/mcld/ADT/Flags.h
index 0091cea..d38d941 100644
--- a/include/mcld/ADT/Flags.h
+++ b/include/mcld/ADT/Flags.h
@@ -28,10 +28,10 @@
Flags(Enum pFlag)
: m_Data(pFlag) {}
- Flags(int pFlag = 0x0)
+ Flags(unsigned int pFlag = 0x0)
: m_Data(pFlag) {}
- operator int () const
+ operator unsigned int () const
{ return m_Data; }
bool operator! () const
@@ -46,11 +46,6 @@
Flags operator& (Enum pMask ) const
{ return Flags(m_Data & pMask); }
- Flags& operator&= (int pMask ) {
- m_Data &= pMask;
- return *this;
- }
-
Flags& operator&= (unsigned int pMask ) {
m_Data &= pMask;
return *this;
@@ -97,7 +92,7 @@
{ return Flags(~m_Data); }
private:
- int m_Data;
+ unsigned int m_Data;
};
} // namespace of mcld
diff --git a/include/mcld/ADT/HashBase.h b/include/mcld/ADT/HashBase.h
index 76410ab..896f5b8 100644
--- a/include/mcld/ADT/HashBase.h
+++ b/include/mcld/ADT/HashBase.h
@@ -103,6 +103,8 @@
/// initialize the hash table.
void init(unsigned int pInitSize);
+ void clear();
+
/// lookUpBucketFor - search the index of bucket whose key is p>ey
// @return the index of the found bucket
unsigned int lookUpBucketFor(const key_type& pKey);
diff --git a/include/mcld/ADT/HashBase.tcc b/include/mcld/ADT/HashBase.tcc
index 62d92b1..165f4ae 100644
--- a/include/mcld/ADT/HashBase.tcc
+++ b/include/mcld/ADT/HashBase.tcc
@@ -80,7 +80,7 @@
typename HashFunctionTy>
HashTableImpl<HashEntryTy, HashFunctionTy>::~HashTableImpl()
{
- free(m_Buckets);
+ clear();
}
/// empty - check if the hash table is empty
@@ -105,6 +105,19 @@
m_Buckets = (bucket_type*)calloc(m_NumOfBuckets, sizeof(bucket_type));
}
+/// clear - clear the hash table.
+template<typename HashEntryTy,
+ typename HashFunctionTy>
+void HashTableImpl<HashEntryTy, HashFunctionTy>::clear()
+{
+ free(m_Buckets);
+
+ m_Buckets = 0;
+ m_NumOfBuckets = 0;
+ m_NumOfEntries = 0;
+ m_NumOfTombstones = 0;
+}
+
/// lookUpBucketFor - look up the bucket whose key is pKey
template<typename HashEntryTy,
typename HashFunctionTy>
diff --git a/include/mcld/ADT/HashEntryFactory.h b/include/mcld/ADT/HashEntryFactory.h
new file mode 100644
index 0000000..42aa5e7
--- /dev/null
+++ b/include/mcld/ADT/HashEntryFactory.h
@@ -0,0 +1,36 @@
+//===- HashEntryFactory.h --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_HASH_ENTRY_FACTORY_H
+#define MCLD_HASH_ENTRY_FACTORY_H
+
+namespace mcld {
+
+/** \class HashEntryFactory
+ * \brief HashEntryFactoy is a factory wrapper for those entries who have
+ * factory methods.
+ */
+template<typename HashEntryTy>
+class HashEntryFactory
+{
+public:
+ typedef HashEntryTy entry_type;
+ typedef typename HashEntryTy::key_type key_type;
+
+public:
+ entry_type* produce(const key_type& pKey)
+ { return HashEntryTy::Create(pKey); }
+
+ void destroy(entry_type*& pEntry)
+ { HashEntryTy::Destroy(pEntry); }
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/ADT/HashIterator.h b/include/mcld/ADT/HashIterator.h
index e25df77..078b20a 100644
--- a/include/mcld/ADT/HashIterator.h
+++ b/include/mcld/ADT/HashIterator.h
@@ -30,7 +30,7 @@
public:
ChainIteratorBase()
- : m_pHashTable(0), m_HashValue(0), m_Index(0), m_EndIndex(0)
+ : m_pHashTable(0), m_Index(0), m_HashValue(0), m_EndIndex(0)
{ }
ChainIteratorBase(HashTableImplTy* pTable, const key_type& pKey)
@@ -64,15 +64,15 @@
ChainIteratorBase(const ChainIteratorBase& pCopy)
: m_pHashTable(pCopy.m_pHashTable),
m_Index(pCopy.m_Index),
- m_EndIndex(pCopy.m_EndIndex),
- m_HashValue(pCopy.m_HashValue)
+ m_HashValue(pCopy.m_HashValue),
+ m_EndIndex(pCopy.m_EndIndex)
{ }
ChainIteratorBase& assign(const ChainIteratorBase& pCopy) {
m_pHashTable = pCopy.m_pHashTable;
m_Index = pCopy.m_Index;
- m_EndIndex = pCopy.m_EndIndex;
m_HashValue = pCopy.m_HashValue;
+ m_EndIndex = pCopy.m_EndIndex;
return *this;
}
diff --git a/include/mcld/ADT/HashTable.h b/include/mcld/ADT/HashTable.h
index dfc2f5a..0b6757e 100644
--- a/include/mcld/ADT/HashTable.h
+++ b/include/mcld/ADT/HashTable.h
@@ -6,22 +6,21 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#ifndef MCLD_HASH_TABLE_H
#define MCLD_HASH_TABLE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include "mcld/ADT/HashBase.h"
-#include "mcld/ADT/HashIterator.h"
-#include "mcld/ADT/Uncopyable.h"
-#include "mcld/ADT/TypeTraits.h"
-#include "mcld/Support/Allocators.h"
+#include <mcld/ADT/HashBase.h>
+#include <mcld/ADT/HashIterator.h>
+#include <mcld/ADT/HashEntryFactory.h>
+#include <mcld/ADT/Uncopyable.h>
+#include <mcld/ADT/TypeTraits.h>
+#include <mcld/Support/Allocators.h>
#include <utility>
-namespace mcld
-{
+namespace mcld {
/** \class HashTable
* \brief HashTable is a hash table which follows boost::unordered_map, but it
@@ -33,7 +32,7 @@
*/
template<typename HashEntryTy,
typename HashFunctionTy,
- typename EntryFactoryTy>
+ typename EntryFactoryTy = HashEntryFactory<HashEntryTy> >
class HashTable : public HashTableImpl<HashEntryTy, HashFunctionTy>,
private Uncopyable
{
diff --git a/include/mcld/ADT/HashTable.tcc b/include/mcld/ADT/HashTable.tcc
index 7439982..d0040ae 100644
--- a/include/mcld/ADT/HashTable.tcc
+++ b/include/mcld/ADT/HashTable.tcc
@@ -51,8 +51,8 @@
BaseTy::m_Buckets[i].Entry = bucket_type::getEmptyBucket();
}
}
- BaseTy::m_NumOfEntries = 0;
- BaseTy::m_NumOfTombstones = 0;
+
+ BaseTy::clear();
}
/// insert - insert a new element to the container. If the element already
diff --git a/include/mcld/ADT/StringEntry.h b/include/mcld/ADT/StringEntry.h
index 09c8dfe..e6d1c20 100644
--- a/include/mcld/ADT/StringEntry.h
+++ b/include/mcld/ADT/StringEntry.h
@@ -69,7 +69,7 @@
private:
DataType m_Value;
uint16_t m_KeyLen;
- char m_Key[0];
+ char m_Key[];
friend class StringEntryFactory<DataType>;
};
@@ -123,7 +123,7 @@
private:
llvm::StringRef m_Value;
uint16_t m_KeyLen;
- char m_Key[0];
+ char m_Key[];
friend class StringEntryFactory<llvm::StringRef>;
};
diff --git a/include/mcld/ADT/StringHash.h b/include/mcld/ADT/StringHash.h
index f100a49..757287c 100644
--- a/include/mcld/ADT/StringHash.h
+++ b/include/mcld/ADT/StringHash.h
@@ -13,7 +13,9 @@
#include <gtest.h>
#endif
#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/DataTypes.h>
#include <llvm/Support/ErrorHandling.h>
+#include <cctype>
#include <functional>
namespace mcld
@@ -31,16 +33,17 @@
DEK,
BP,
FNV,
- AP
+ AP,
+ ES
};
-/** \class template<size_t TYPE> StringHash
+/** \class template<uint32_t TYPE> StringHash
* \brief the template StringHash class, for specification
*/
-template<size_t TYPE>
-struct StringHash : public std::unary_function<const llvm::StringRef&, size_t>
+template<uint32_t TYPE>
+struct StringHash : public std::unary_function<const llvm::StringRef&, uint32_t>
{
- size_t operator()(const llvm::StringRef& pKey) const
+ uint32_t operator()(const llvm::StringRef& pKey) const
{
llvm::report_fatal_error("Undefined StringHash function.\n");
}
@@ -50,13 +53,13 @@
* \brief RS StringHash funciton
*/
template<>
-struct StringHash<RS> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<RS> : public std::unary_function<const llvm::StringRef&, uint32_t>
{
- size_t operator()(const llvm::StringRef& pKey) const
+ uint32_t operator()(const llvm::StringRef& pKey) const
{
const unsigned int b = 378551;
- size_t a = 63689;
- size_t hash_val = 0;
+ uint32_t a = 63689;
+ uint32_t hash_val = 0;
for(unsigned int i = 0; i < pKey.size(); ++i) {
hash_val = hash_val * a + pKey[i];
@@ -70,11 +73,11 @@
* \brief JS hash funciton
*/
template<>
-struct StringHash<JS> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<JS> : public std::unary_function<const llvm::StringRef&, uint32_t>
{
- size_t operator()(const llvm::StringRef& pKey) const
+ uint32_t operator()(const llvm::StringRef& pKey) const
{
- size_t hash_val = 1315423911;
+ uint32_t hash_val = 1315423911;
for(unsigned int i = 0; i < pKey.size(); ++i) {
hash_val ^= ((hash_val << 5) + pKey[i] + (hash_val >> 2));
@@ -87,16 +90,16 @@
* \brief P.J. Weinberger hash function
*/
template<>
-struct StringHash<PJW> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<PJW> : public std::unary_function<const llvm::StringRef&, uint32_t>
{
- size_t operator()(const llvm::StringRef& pKey) const
+ uint32_t operator()(const llvm::StringRef& pKey) const
{
const unsigned int BitsInUnsignedInt = (unsigned int)(sizeof(unsigned int) * 8);
const unsigned int ThreeQuarters = (unsigned int)((BitsInUnsignedInt * 3) / 4);
const unsigned int OneEighth = (unsigned int)(BitsInUnsignedInt / 8);
const unsigned int HighBits = (unsigned int)(0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);
- size_t hash_val = 0;
- size_t test = 0;
+ uint32_t hash_val = 0;
+ uint32_t test = 0;
for(unsigned int i = 0; i < pKey.size(); ++i) {
hash_val = (hash_val << OneEighth) + pKey[i];
@@ -113,12 +116,12 @@
* \brief ELF hash function.
*/
template<>
-struct StringHash<ELF> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<ELF> : public std::unary_function<const llvm::StringRef&, uint32_t>
{
- size_t operator()(const llvm::StringRef& pKey) const
+ uint32_t operator()(const llvm::StringRef& pKey) const
{
- size_t hash_val = 0;
- size_t x = 0;
+ uint32_t hash_val = 0;
+ uint32_t x = 0;
for (unsigned int i = 0; i < pKey.size(); ++i) {
hash_val = (hash_val << 4) + pKey[i];
@@ -134,14 +137,14 @@
* \brief BKDR hash function
*/
template<>
-struct StringHash<BKDR> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<BKDR> : public std::unary_function<const llvm::StringRef&, uint32_t>
{
- size_t operator()(const llvm::StringRef& pKey) const
+ uint32_t operator()(const llvm::StringRef& pKey) const
{
- const size_t seed = 131;
- size_t hash_val = 0;
+ const uint32_t seed = 131;
+ uint32_t hash_val = 0;
- for(size_t i = 0; i < pKey.size(); ++i)
+ for(uint32_t i = 0; i < pKey.size(); ++i)
hash_val = (hash_val * seed) + pKey[i];
return hash_val;
}
@@ -153,13 +156,13 @@
* 0.049s in 100000 test
*/
template<>
-struct StringHash<SDBM> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<SDBM> : public std::unary_function<const llvm::StringRef&, uint32_t>
{
- size_t operator()(const llvm::StringRef& pKey) const
+ uint32_t operator()(const llvm::StringRef& pKey) const
{
- size_t hash_val = 0;
+ uint32_t hash_val = 0;
- for(size_t i = 0; i < pKey.size(); ++i)
+ for(uint32_t i = 0; i < pKey.size(); ++i)
hash_val = pKey[i] + (hash_val << 6) + (hash_val << 16) - hash_val;
return hash_val;
}
@@ -170,13 +173,13 @@
* 0.057s in 100000 test
*/
template<>
-struct StringHash<DJB> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<DJB> : public std::unary_function<const llvm::StringRef&, uint32_t>
{
- size_t operator()(const llvm::StringRef& pKey) const
+ uint32_t operator()(const llvm::StringRef& pKey) const
{
- size_t hash_val = 5381;
+ uint32_t hash_val = 5381;
- for(size_t i = 0; i < pKey.size(); ++i)
+ for(uint32_t i = 0; i < pKey.size(); ++i)
hash_val = ((hash_val << 5) + hash_val) + pKey[i];
return hash_val;
@@ -188,13 +191,13 @@
* 0.60s
*/
template<>
-struct StringHash<DEK> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<DEK> : public std::unary_function<const llvm::StringRef&, uint32_t>
{
- size_t operator()(const llvm::StringRef& pKey) const
+ uint32_t operator()(const llvm::StringRef& pKey) const
{
- size_t hash_val = pKey.size();
+ uint32_t hash_val = pKey.size();
- for(size_t i = 0; i < pKey.size(); ++i)
+ for(uint32_t i = 0; i < pKey.size(); ++i)
hash_val = ((hash_val << 5) ^ (hash_val >> 27)) ^ pKey[i];
return hash_val;
@@ -206,12 +209,12 @@
* 0.057s
*/
template<>
-struct StringHash<BP> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<BP> : public std::unary_function<const llvm::StringRef&, uint32_t>
{
- size_t operator()(const llvm::StringRef& pKey) const
+ uint32_t operator()(const llvm::StringRef& pKey) const
{
- size_t hash_val = 0;
- for(size_t i = 0; i < pKey.size(); ++i)
+ uint32_t hash_val = 0;
+ for(uint32_t i = 0; i < pKey.size(); ++i)
hash_val = hash_val << 7 ^ pKey[i];
return hash_val;
@@ -223,13 +226,13 @@
* 0.058s
*/
template<>
-struct StringHash<FNV> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<FNV> : public std::unary_function<const llvm::StringRef&, uint32_t>
{
- size_t operator()(const llvm::StringRef& pKey) const
+ uint32_t operator()(const llvm::StringRef& pKey) const
{
- const size_t fnv_prime = 0x811C9DC5;
- size_t hash_val = 0;
- for(size_t i = 0; i < pKey.size(); ++i) {
+ const uint32_t fnv_prime = 0x811C9DC5;
+ uint32_t hash_val = 0;
+ for(uint32_t i = 0; i < pKey.size(); ++i) {
hash_val *= fnv_prime;
hash_val ^= pKey[i];
}
@@ -243,13 +246,13 @@
* 0.060s
*/
template<>
-struct StringHash<AP> : public std::unary_function<const llvm::StringRef&, size_t>
+struct StringHash<AP> : public std::unary_function<const llvm::StringRef&, uint32_t>
{
- size_t operator()(const llvm::StringRef& pKey) const
+ uint32_t operator()(const llvm::StringRef& pKey) const
{
unsigned int hash_val = 0xAAAAAAAA;
- for(size_t i = 0; i < pKey.size(); ++i) {
+ for(uint32_t i = 0; i < pKey.size(); ++i) {
hash_val ^= ((i & 1) == 0)?
((hash_val << 7) ^ pKey[i] * (hash_val >> 3)):
(~((hash_val << 11) + (pKey[i] ^ (hash_val >> 5))));
@@ -259,7 +262,83 @@
}
};
-/** \class template<size_t TYPE> StringCompare
+/** \class StringHash<ES>
+ * \brief This is a revision of Edward Sayers' string characteristic function.
+ *
+ * 31-28 27 26 25 - 0
+ * +----+---+---+------------+
+ * | . | N | - | a/A ~ z/Z |
+ * +----+---+---+------------+
+ *
+ * . (bit 31~28) - The number of '.' characters
+ * N (bit 27) - Are there any numbers in the string
+ * - (bit 26) - Does the string have '-' character
+ * bit 25~0 - Bit 25 is set only if the string contains a 'a' or 'A', and
+ * Bit 24 is set only if ... 'b' or 'B', ...
+ */
+template<>
+struct StringHash<ES> : public std::unary_function<const llvm::StringRef&, uint32_t>
+{
+ uint32_t operator()(const llvm::StringRef& pString) const
+ {
+ uint32_t result = 0x0;
+ unsigned int dot = 0;
+ std::string::size_type idx;
+ for (idx = 0; idx < pString.size(); ++idx) {
+ int cur_char = pString[idx];
+
+ if ('.' == cur_char) {
+ ++dot;
+ continue;
+ }
+
+ if (isdigit(cur_char)) {
+ result |= (1 << 27);
+ continue;
+ }
+
+ if ('_' == cur_char) {
+ result |= (1 << 26);
+ continue;
+ }
+
+ if (isupper(cur_char)) {
+ result |= (1 << (cur_char - 'A'));
+ continue;
+ }
+
+ if (islower(cur_char)) {
+ result |= (1 << (cur_char - 'a'));
+ continue;
+ }
+ }
+ result |= (dot << 28);
+ return result;
+ }
+
+
+ /** \func may_include
+ * \brief is it possible that pRule is a sub-string of pInString
+ */
+ static bool may_include(uint32_t pRule, uint32_t pInString)
+ {
+ uint32_t in_c = pInString << 4;
+ uint32_t r_c = pRule << 4;
+
+ uint32_t res = (in_c ^ r_c) & r_c;
+ if (0 != res)
+ return false;
+
+ uint32_t in_dot = pInString >> 28;
+ uint32_t r_dot = pRule >> 28;
+ if (r_dot > in_dot)
+ return false;
+
+ return true;
+ }
+};
+
+/** \class template<uint32_t TYPE> StringCompare
* \brief the template StringCompare class, for specification
*/
template<typename STRING_TYPE>
diff --git a/include/mcld/ADT/TreeBase.h b/include/mcld/ADT/TreeBase.h
index 10e0892..6fb3bf6 100644
--- a/include/mcld/ADT/TreeBase.h
+++ b/include/mcld/ADT/TreeBase.h
@@ -12,8 +12,7 @@
#include <cstddef>
-namespace mcld
-{
+namespace mcld {
class NodeBase
{
@@ -39,7 +38,7 @@
} // namespace of template proxy
-struct TreeIteratorBase
+class TreeIteratorBase
{
public:
enum Direct {
diff --git a/include/mcld/AttributeOption.h b/include/mcld/AttributeOption.h
new file mode 100644
index 0000000..18d7278
--- /dev/null
+++ b/include/mcld/AttributeOption.h
@@ -0,0 +1,38 @@
+//===- AttributeOption.h --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ATTRIBUTE_OPTIONS_H
+#define MCLD_ATTRIBUTE_OPTIONS_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/MC/Attribute.h>
+
+namespace mcld {
+
+class AttributeOption
+{
+public:
+ AttributeOption();
+ ~AttributeOption();
+
+ const Attribute& predefined() const { return m_Predefined; }
+ Attribute& predefined() { return m_Predefined; }
+
+ const AttrConstraint& constraint() const { return m_Constraint; }
+ AttrConstraint& constraint() { return m_Constraint; }
+
+private:
+ Attribute m_Predefined;
+ AttrConstraint m_Constraint;
+};
+
+} // namespace mcld
+
+#endif
+
diff --git a/include/mcld/BitcodeOption.h b/include/mcld/BitcodeOption.h
new file mode 100644
index 0000000..4e9a5e1
--- /dev/null
+++ b/include/mcld/BitcodeOption.h
@@ -0,0 +1,49 @@
+//===- BitcodeOption.h ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_BITCODE_OPTIONS_H
+#define MCLD_BITCODE_OPTIONS_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Support/Path.h>
+
+namespace mcld {
+
+/** \class BitcodeOption
+ * \brief BitcodeOption represents the options of bitcode on the command line.
+ */
+class BitcodeOption
+{
+public:
+ BitcodeOption();
+
+ ~BitcodeOption();
+
+ void setPosition(unsigned int pPosition) { m_Position = pPosition; }
+
+ unsigned int getPosition() const { return m_Position; }
+
+ void setPath(const sys::fs::Path& pPath) { m_Path = pPath; }
+
+ const sys::fs::Path& getPath() const { return m_Path; }
+
+ bool hasDefined() const;
+
+private:
+ int m_Position;
+
+ sys::fs::Path m_Path;
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/CodeGen/MCLinker.h b/include/mcld/CodeGen/MCLinker.h
new file mode 100644
index 0000000..34ddcb7
--- /dev/null
+++ b/include/mcld/CodeGen/MCLinker.h
@@ -0,0 +1,85 @@
+//===- MCLinker.h ---------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// MCLinker is a base class inherited by target specific linker.
+// This class primarily handles common functionality used by all linkers.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_CODEGEN_MCLINKER_H
+#define MCLD_CODEGEN_MCLINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <llvm/CodeGen/MachineFunctionPass.h>
+
+namespace llvm {
+
+class Module;
+class MachineFunction;
+
+} // namespace of llvm
+
+namespace mcld {
+
+class Module;
+class MemoryArea;
+class IRBuilder;
+class LinkerConfig;
+class Linker;
+
+/** \class MCLinker
+* \brief MCLinker provides a linking pass for standard compilation flow
+*
+* MCLinker is responded for
+* - provide an interface for target-specific linker
+* - set up environment for ObjectLinker
+* - perform linking
+*
+* @see MachineFunctionPass ObjectLinker
+*/
+class MCLinker : public llvm::MachineFunctionPass
+{
+protected:
+ // Constructor. Although MCLinker has only two arguments,
+ // TargetMCLinker should handle
+ // - enabled attributes
+ // - the default attribute
+ // - the default link script
+ // - the standard symbols
+ MCLinker(LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ MemoryArea& pOutput);
+
+public:
+ virtual ~MCLinker();
+
+ virtual bool doInitialization(llvm::Module &pM);
+
+ virtual bool doFinalization(llvm::Module &pM);
+
+ virtual bool runOnMachineFunction(llvm::MachineFunction& pMFn);
+
+protected:
+ void initializeInputTree(IRBuilder& pBuilder);
+
+protected:
+ LinkerConfig& m_Config;
+ mcld::Module& m_Module;
+ MemoryArea& m_Output;
+ IRBuilder* m_pBuilder;
+ Linker* m_pLinker;
+
+private:
+ static char m_ID;
+};
+
+} // namespace of MC Linker
+
+#endif
+
diff --git a/include/mcld/CodeGen/SectLinker.h b/include/mcld/CodeGen/SectLinker.h
deleted file mode 100644
index 4ed2907..0000000
--- a/include/mcld/CodeGen/SectLinker.h
+++ /dev/null
@@ -1,104 +0,0 @@
-//===- SectLinker.h -------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//SectLinker is a base class inherited by target specific linker.
-//This class primarily handles common functionality used by all linkers.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_SECTION_LINKER_H
-#define MCLD_SECTION_LINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <llvm/CodeGen/MachineFunctionPass.h>
-#include <mcld/Support/PositionDependentOption.h>
-#include <vector>
-
-namespace llvm
-{
-class Module;
-class MachineFunction;
-} // namespace of llvm
-
-namespace mcld
-{
-class MCLDInfo;
-class MCLDFile;
-class MCLDDriver;
-class TargetLDBackend;
-class AttributeFactory;
-class SectLinkerOption;
-class MemoryAreaFactory;
-
-/** \class SectLinker
-* \brief SectLinker provides a linking pass for standard compilation flow
-*
-* SectLinker is responded for
-* - provide an interface for target-specific SectLinekr
-* - set up environment for MCLDDriver
-* - control AsmPrinter, make sure AsmPrinter has already prepared
-* all SectionDatas for linking
-*
-* SectLinker resolves the absolue paths of input arguments.
-*
-* @see MachineFunctionPass MCLDDriver
-*/
-class SectLinker : public llvm::MachineFunctionPass
-{
-protected:
- // Constructor. Although SectLinker has only two arguments,
- // TargetSectLinker should handle
- // - enabled attributes
- // - the default attribute
- // - the default link script
- // - the standard symbols
- SectLinker(SectLinkerOption &pOption,
- TargetLDBackend &pLDBackend);
-
-public:
- virtual ~SectLinker();
-
- /// doInitialization - Read all parameters and set up the AsmPrinter.
- /// If your pass overrides this, it must make sure to explicitly call
- /// this implementation.
- virtual bool doInitialization(llvm::Module &pM);
-
- /// doFinalization - Shut down the AsmPrinter, and do really linking.
- /// If you override this in your pass, you must make sure to call it
- /// explicitly.
- virtual bool doFinalization(llvm::Module &pM);
-
- /// runOnMachineFunction
- /// redirect to AsmPrinter
- virtual bool runOnMachineFunction(llvm::MachineFunction& pMFn);
-
-protected:
- void initializeInputTree(const PositionDependentOptions &pOptions) const;
-
- void initializeInputOutput(MCLDInfo& pLDInfo);
-
- MemoryAreaFactory* memAreaFactory()
- { return m_pMemAreaFactory; }
-
-private:
- SectLinkerOption *m_pOption;
-
-protected:
- TargetLDBackend *m_pLDBackend;
- MCLDDriver *m_pLDDriver;
- MemoryAreaFactory *m_pMemAreaFactory;
-
-private:
- static char m_ID;
-};
-
-} // namespace of MC Linker
-
-#endif
-
diff --git a/include/mcld/CodeGen/SectLinkerOption.h b/include/mcld/CodeGen/SectLinkerOption.h
deleted file mode 100644
index 78c8f53..0000000
--- a/include/mcld/CodeGen/SectLinkerOption.h
+++ /dev/null
@@ -1,57 +0,0 @@
-//===- SectLinkerOption.h ---------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_SECTLINKERDATA_H
-#define MCLD_SECTLINKERDATA_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/Support/PositionDependentOption.h>
-
-#include <string>
-
-namespace mcld
-{
- class PositionDependentOption;
-
- /** \class SectLinkerOption
- * \brief This file collects inputs to linker.
- */
- class SectLinkerOption
- {
- public:
- // Constructor.
- SectLinkerOption(MCLDInfo &pLDInfo);
-
- // ----- Position-dependent Options ----- //
- inline void appendOption(PositionDependentOption *pOption)
- { m_PosDepOptions.push_back(pOption); }
-
- inline void prependOption(PositionDependentOption *pOption)
- { m_PosDepOptions.insert(m_PosDepOptions.begin(), pOption); }
-
- inline const PositionDependentOptions &pos_dep_options() const
- { return m_PosDepOptions; }
- inline PositionDependentOptions &pos_dep_options()
- { return m_PosDepOptions; }
-
- inline const MCLDInfo &info() const { return *m_pLDInfo; }
- inline MCLDInfo &info() { return *m_pLDInfo; }
-
- ~SectLinkerOption();
-
- private:
- MCLDInfo *m_pLDInfo;
- PositionDependentOptions m_PosDepOptions;
- };
-
-} // namespace of mcld
-
-#endif
diff --git a/include/mcld/Config/Config.h b/include/mcld/Config/Config.h
index 8daa109..f604109 100644
--- a/include/mcld/Config/Config.h
+++ b/include/mcld/Config/Config.h
@@ -23,7 +23,12 @@
# define MCLD_ON_WIN32 1
#endif
-#define MCLD_VERSION "Phoenix - 1.4.0"
+#define MCLD_VERSION "RockBull - 2.0.0"
+
+#define MCLD_REGION_CHUNK_SIZE 32
+#define MCLD_NUM_OF_INPUTS 32
+#define MCLD_SECTIONS_PER_INPUT 16
+#define MCLD_SYMBOLS_PER_INPUT 128
#endif
diff --git a/include/mcld/Config/Config.h.in b/include/mcld/Config/Config.h.in
index c0e7e0a..f025393 100644
--- a/include/mcld/Config/Config.h.in
+++ b/include/mcld/Config/Config.h.in
@@ -11,6 +11,10 @@
#define @MCLD_ON_PLATFORM@ 1
#define MCLD_VERSION "@MCLD_VERSION@"
+#define MCLD_REGION_CHUNK_SIZE 32
+#define MCLD_NUM_OF_INPUTS 32
+#define MCLD_SECTIONS_PER_INPUT 16
+#define MCLD_SYMBOLS_PER_INPUT 128
#endif
diff --git a/include/mcld/Config/Linkers.def b/include/mcld/Config/Linkers.def
index 2781461..c0a852f 100644
--- a/include/mcld/Config/Linkers.def
+++ b/include/mcld/Config/Linkers.def
@@ -1,4 +1,4 @@
-//===- llvm/Config/Linkers.def - LLVM Linkers -------------------*- C++ -*-===//
+//===- llvm/Config/Linkers.def - MCLinkers ----------------------*- C++ -*-===//
//
// The MCLinker Project
//
@@ -7,13 +7,13 @@
//
//===----------------------------------------------------------------------===//
//
-// This file enumerates all of the linkers supported by this build of LLVM.
-// Clients of this file should define the LLVM_LINKER macro to be a function-like
+// This file enumerates all of the linkers supported by this build of MCLinker.
+// Clients of this file should define the MCLD_LINKER macro to be a function-like
// macro with a single parameter (the name of the target whose exe/dso can be
// generated); including this file will then enumerate all of the targets with
// linkers.
//
-// The set of targets supported by LLVM is generated at configuration
+// The set of targets supported by MCLD is generated at configuration
// time, at which point this header is generated. Do not modify this
// header directly.
//
@@ -23,11 +23,12 @@
// Hand-coded for Android build
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LINKER
-# error Please define the macro LLVM_LINKER(TargetName)
+#ifndef MCLD_LINKER
+# error Please define the macro MCLD_LINKER(TargetName)
#endif
-#define LLVM_TARGET LLVM_LINKER
+#define LLVM_TARGET MCLD_LINKER
#include <llvm/Config/Targets.def>
+#undef LLVM_TARGET
-#undef LLVM_LINKER
+#undef MCLD_LINKER
diff --git a/include/mcld/Config/Linkers.def.in b/include/mcld/Config/Linkers.def.in
index 0e09040..e8b870b 100644
--- a/include/mcld/Config/Linkers.def.in
+++ b/include/mcld/Config/Linkers.def.in
@@ -1,4 +1,4 @@
-//===- llvm/Config/Linkers.def - LLVM Linkers -------------------*- C++ -*-===//
+//===- llvm/Config/Linkers.def - MCLinkers ----------------------*- C++ -*-===//
//
// The MCLinker Project
//
@@ -7,22 +7,22 @@
//
//===----------------------------------------------------------------------===//
//
-// This file enumerates all of the linkers supported by this build of LLVM.
-// Clients of this file should define the LLVM_LINKER macro to be a function-like
+// This file enumerates all of the linkers supported by this build of MCLinker.
+// Clients of this file should define the MCLD_LINKER macro to be a function-like
// macro with a single parameter (the name of the target whose exe/dso can be
// generated); including this file will then enumerate all of the targets with
// linkers.
//
-// The set of targets supported by LLVM is generated at configuration
+// The set of targets supported by MCLD is generated at configuration
// time, at which point this header is generated. Do not modify this
// header directly.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LINKER
-# error Please define the macro LLVM_LINKER(TargetName)
+#ifndef MCLD_LINKER
+# error Please define the macro MCLD_LINKER(TargetName)
#endif
-@LLVM_ENUM_LINKERS@
+@MCLD_ENUM_LINKERS@
-#undef LLVM_LINKER
+#undef MCLD_LINKER
diff --git a/include/mcld/Config/Targets.def b/include/mcld/Config/Targets.def
index a0981d6..db05cce 100644
--- a/include/mcld/Config/Targets.def
+++ b/include/mcld/Config/Targets.def
@@ -1,6 +1,6 @@
-/*===- llvm/Config/Targets.def - LLVM Target Architectures ------*- C++ -*-===*\
+/*===- llvm/Config/Targets.def - MCLD Target Architectures ------*- C++ -*-===*\
|* *|
-|* The MCLinker Project *|
+|* The MCLinker Project *|
|* *|
|* This file is distributed under the University of Illinois Open Source *|
|* License. See LICENSE.TXT for details. *|
@@ -8,12 +8,12 @@
|*===----------------------------------------------------------------------===*|
|* *|
|* This file enumerates all of the target architectures supported by *|
-|* this build of LLVM. Clients of this file should define the *|
-|* LLVM_TARGET macro to be a function-like macro with a single *|
+|* this build of MCLD. Clients of this file should define the *|
+|* MCLD_TARGET macro to be a function-like macro with a single *|
|* parameter (the name of the target); including this file will then *|
|* enumerate all of the targets. *|
|* *|
-|* The set of targets supported by LLVM is generated at configuration *|
+|* The set of targets supported by MCLD is generated at configuration *|
|* time, at which point this header is generated. Do not modify this *|
|* header directly. *|
|* *|
@@ -23,10 +23,12 @@
// Hand-coded for Android build
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TARGET
-# error Please define the macro LLVM_TARGET(TargetName)
+#ifndef MCLD_TARGET
+# error Please define the macro MCLD_TARGET(TargetName)
#endif
+#define LLVM_TARGET MCLD_TARGET
#include <llvm/Config/Targets.def>
-
#undef LLVM_TARGET
+
+#undef MCLD_TARGET
diff --git a/include/mcld/Config/Targets.def.in b/include/mcld/Config/Targets.def.in
index a73b9b7..7423904 100644
--- a/include/mcld/Config/Targets.def.in
+++ b/include/mcld/Config/Targets.def.in
@@ -1,6 +1,6 @@
-/*===- llvm/Config/Targets.def - LLVM Target Architectures ------*- C++ -*-===*\
+/*===- llvm/Config/Targets.def - MCLD Target Architectures ------*- C++ -*-===*\
|* *|
-|* The MCLinker Project *|
+|* The MCLinker Project *|
|* *|
|* This file is distributed under the University of Illinois Open Source *|
|* License. See LICENSE.TXT for details. *|
@@ -8,21 +8,21 @@
|*===----------------------------------------------------------------------===*|
|* *|
|* This file enumerates all of the target architectures supported by *|
-|* this build of LLVM. Clients of this file should define the *|
-|* LLVM_TARGET macro to be a function-like macro with a single *|
+|* this build of MCLD. Clients of this file should define the *|
+|* MCLD_TARGET macro to be a function-like macro with a single *|
|* parameter (the name of the target); including this file will then *|
|* enumerate all of the targets. *|
|* *|
-|* The set of targets supported by LLVM is generated at configuration *|
+|* The set of targets supported by MCLD is generated at configuration *|
|* time, at which point this header is generated. Do not modify this *|
|* header directly. *|
|* *|
\*===----------------------------------------------------------------------===*/
-#ifndef LLVM_TARGET
-# error Please define the macro LLVM_TARGET(TargetName)
+#ifndef MCLD_TARGET
+# error Please define the macro MCLD_TARGET(TargetName)
#endif
-@LLVM_ENUM_TARGETS@
+@MCLD_ENUM_TARGETS@
-#undef LLVM_TARGET
+#undef MCLD_TARGET
diff --git a/include/mcld/Environment.h b/include/mcld/Environment.h
new file mode 100644
index 0000000..d543566
--- /dev/null
+++ b/include/mcld/Environment.h
@@ -0,0 +1,23 @@
+//===- Environment.h ------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ENVIRONMENT_H
+#define MCLD_ENVIRONMENT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+namespace mcld {
+
+void Initialize();
+
+void Finalize();
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/LD/AlignFragment.h b/include/mcld/Fragment/AlignFragment.h
similarity index 91%
rename from include/mcld/LD/AlignFragment.h
rename to include/mcld/Fragment/AlignFragment.h
index 4c5582c..14d0051 100644
--- a/include/mcld/LD/AlignFragment.h
+++ b/include/mcld/Fragment/AlignFragment.h
@@ -12,10 +12,9 @@
#include <gtest.h>
#endif
-#include <mcld/LD/Fragment.h>
+#include <mcld/Fragment/Fragment.h>
-namespace mcld
-{
+namespace mcld {
class SectionData;
@@ -37,11 +36,12 @@
void setEmitNops(bool pValue) { m_bEmitNops = pValue; }
- static bool classof(const Fragment *F) {
- return F->getKind() == Fragment::Alignment;
- }
+ static bool classof(const Fragment *F)
+ { return F->getKind() == Fragment::Alignment; }
static bool classof(const AlignFragment *) { return true; }
+ size_t size() const;
+
private:
/// Alignment - The alignment to ensure, in bytes.
unsigned int m_Alignment;
diff --git a/include/mcld/LD/FillFragment.h b/include/mcld/Fragment/FillFragment.h
similarity index 92%
rename from include/mcld/LD/FillFragment.h
rename to include/mcld/Fragment/FillFragment.h
index db29111..af78237 100644
--- a/include/mcld/LD/FillFragment.h
+++ b/include/mcld/Fragment/FillFragment.h
@@ -14,10 +14,9 @@
#include <llvm/Support/DataTypes.h>
-#include <mcld/LD/Fragment.h>
+#include <mcld/Fragment/Fragment.h>
-namespace mcld
-{
+namespace mcld {
class SectionData;
@@ -31,13 +30,13 @@
unsigned getValueSize() const { return m_ValueSize; }
- uint64_t getSize() const { return m_Size; }
-
static bool classof(const Fragment *F)
{ return F->getKind() == Fragment::Fillment; }
static bool classof(const FillFragment *) { return true; }
+ size_t size() const { return m_Size; }
+
private:
/// m_Value - Value used for filling bytes
int64_t m_Value;
diff --git a/include/mcld/LD/Fragment.h b/include/mcld/Fragment/Fragment.h
similarity index 81%
rename from include/mcld/LD/Fragment.h
rename to include/mcld/Fragment/Fragment.h
index 1baa8df..b3d072d 100644
--- a/include/mcld/LD/Fragment.h
+++ b/include/mcld/Fragment/Fragment.h
@@ -6,19 +6,20 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_FRAGMENT_H
-#define MCLD_FRAGMENT_H
+#ifndef MCLD_FRAGMENT_FRAGMENT_H
+#define MCLD_FRAGMENT_FRAGMENT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <llvm/ADT/ilist_node.h>
+
#include <llvm/Support/DataTypes.h>
#include <cstddef>
+#include <cassert>
-namespace mcld
-{
+namespace mcld {
class SectionData;
@@ -33,7 +34,9 @@
Fillment,
Region,
Relocation,
- Target
+ Target,
+ Stub,
+ Null
};
public:
@@ -49,16 +52,19 @@
void setParent(SectionData *pValue) { m_pParent = pValue; }
- uint64_t getOffset() const { return m_Offset; }
+ uint64_t getOffset() const;
void setOffset(uint64_t pOffset) { m_Offset = pOffset; }
- unsigned int getLayoutOrder() const { return m_LayoutOrder; }
-
- void setLayoutOrder(unsigned int pValue) { m_LayoutOrder = pValue; }
+ bool hasOffset() const;
static bool classof(const Fragment *O) { return true; }
+ virtual size_t size() const {
+ assert(false && "Can not call abstract Fragment::size()!");
+ return 0;
+ }
+
private:
Fragment(const Fragment& ); // DO NOT IMPLEMENT
Fragment& operator=(const Fragment& ); // DO NOT IMPLEMENT
@@ -68,7 +74,6 @@
SectionData* m_pParent;
uint64_t m_Offset;
- unsigned int m_LayoutOrder;
};
diff --git a/include/mcld/MC/MCLinker.h b/include/mcld/Fragment/FragmentLinker.h
similarity index 63%
rename from include/mcld/MC/MCLinker.h
rename to include/mcld/Fragment/FragmentLinker.h
index 9fe78d8..9fd70d0 100644
--- a/include/mcld/MC/MCLinker.h
+++ b/include/mcld/Fragment/FragmentLinker.h
@@ -1,4 +1,4 @@
-//===- MCLinker.h -------------------------------------------------------===//
+//===- FragmentLinker.h ---------------------------------------------------===//
//
// The MCLinker Project
//
@@ -11,45 +11,38 @@
// These APIs do the things which a linker should do.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_MCLINKER_H
-#define MCLD_MCLINKER_H
+#ifndef MCLD_FRAGMENT_FRAGMENT_LINKER_H
+#define MCLD_FRAGMENT_FRAGMENT_LINKER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <set>
#include <string>
-#include <llvm/ADT/ilist.h>
-
-#include <mcld/LD/StaticResolver.h>
-#include <mcld/LD/LDSectionFactory.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/LD/LDFileFormat.h>
-#include <mcld/LD/LDContext.h>
-#include <mcld/LD/Relocation.h>
-#include <mcld/LD/SectionMerger.h>
-#include <mcld/LD/Layout.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Relocation.h>
#include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/SymbolCategory.h>
-#include <mcld/Support/GCFactory.h>
-#include <mcld/Support/GCFactoryListTraits.h>
namespace mcld {
+class Module;
class TargetLDBackend;
-class MCLDInfo;
+class LinkerConfig;
class LDSection;
class LDSectionFactory;
class SectionData;
-class SectionMap;
class Output;
class EhFrame;
class EhFrameHdr;
+class MemoryArea;
+class RelocData;
-/** \class MCLinker
- * \brief MCLinker provides a pass to link object files.
+/** \class FragmentLinker
+ * \brief FragmentLinker provides a pass to link object files.
*/
-class MCLinker
+class FragmentLinker
{
public:
enum DefinePolicy
@@ -65,11 +58,11 @@
};
public:
- MCLinker(TargetLDBackend& pBackend,
- MCLDInfo& pLDInfo,
- SectionMap& pSectionMap);
+ FragmentLinker(const LinkerConfig& pConfig,
+ Module& pModule,
+ TargetLDBackend& pBackend);
- ~MCLinker();
+ ~FragmentLinker();
// ----- about symbols ----- //
/// addDynSymbol - add a symbol and resolve it immediately
@@ -115,52 +108,18 @@
bool finalizeSymbols();
- // ----- sections ----- //
- /// getSectionMap - getSectionMap to change the behavior of SectionMerger
- /// SectionMap& getSectionMap()
- /// { return m_SectionMap; }
-
- /// createSectHdr - for reader and standard/target format to create a section
- /// header. This function will create a new LDSection and return it. If the
- /// output has no related LDSection, this function will also create one and
- /// push into the output.
- LDSection& createSectHdr(const std::string& pName,
- LDFileFormat::Kind pKind,
- uint32_t pType,
- uint32_t pFlag);
-
- /// getOrCreateOutputSectHdr - for reader and standard/target format to get
- /// or create the output's section header
- LDSection& getOrCreateOutputSectHdr(const std::string& pName,
- LDFileFormat::Kind pKind,
- uint32_t pType,
- uint32_t pFlag,
- uint32_t pAlign = 0x0);
-
- /// getOrCreateSectData - for reader to map and perform section merging immediately
- SectionData& getOrCreateSectData(LDSection& pSection);
-
- // ----- eh_frame sections ----- //
- /// addEhFrame - add an exception handling section
- /// @param pInput - the Input contains this section
- /// @param pSection - the input section
- /// @param pArea - the memory area which pSection is within.
- uint64_t addEhFrame(const Input& pInput,
- LDSection& pSection,
- MemoryArea& pArea);
-
// ----- relocations ----- //
- /// addRelocation - add a relocation entry in MCLinker (only for object file)
+ /// addRelocation - add a relocation entry in FragmentLinker (only for object file)
/// @param pType - the type of the relocation
- /// @param pResolveInfo - the symbol should be the symbol in the input file. MCLinker
+ /// @param pSym - the symbol should be the symbol in the input file. FragmentLinker
/// computes the real applied address by the output symbol.
- /// @param pFragmentRef - the fragment reference of the applied address.
+ /// @param pSection - the input relocation section
+ /// @param pOffset - the offset of target section.
/// @param pAddend - the addend value for applying relocation
Relocation* addRelocation(Relocation::Type pType,
- const LDSymbol& pSym,
- ResolveInfo& pResolveInfo,
- FragmentRef& pFragmentRef,
- const LDSection& pSection,
+ LDSymbol& pSym,
+ LDSection& pSection,
+ uint32_t pOffset,
Relocation::Address pAddend = 0);
/// applyRelocations - apply all relocation enties.
@@ -168,32 +127,17 @@
/// syncRelocationResult - After applying relocation, write back relocation target
/// data to output file.
- void syncRelocationResult();
-
- // ----- layout ----- //
- void initSectionMap();
-
- Layout& getLayout()
- { return m_Layout; }
-
- const Layout& getLayout() const
- { return m_Layout; }
-
- bool layout();
-
- // ----- output symbols ----- //
- SymbolCategory& getOutputSymbols()
- { return m_OutputSymbols; }
-
- const SymbolCategory& getOutputSymbols() const
- { return m_OutputSymbols; }
+ void syncRelocationResult(MemoryArea& pOutput);
// ----- capacity ----- //
- MCLDInfo& getLDInfo()
- { return m_LDInfo; }
+ const LinkerConfig& getLDInfo() const { return m_Config; }
- const MCLDInfo& getLDInfo() const
- { return m_LDInfo; }
+ // ----- output attribute ----- //
+ /// isOutputPIC - return whether the output is position-independent
+ bool isOutputPIC() const;
+
+ /// isStaticLink - return whether we're doing static link
+ bool isStaticLink() const;
private:
LDSymbol* defineSymbolForcefully(const llvm::StringRef& pName,
@@ -255,28 +199,34 @@
LDSymbol::ValueType pValue,
FragmentRef* pFragmentRef,
ResolveInfo::Visibility pVisibility);
-private:
- typedef GCFactory<LDSymbol, 0> LDSymbolFactory;
- typedef GCFactory<SectionData, 0> LDSectionDataFactory;
- typedef llvm::iplist<Fragment,
- GCFactoryListTraits<Fragment> > RelocationListType;
- typedef std::set<LDSymbol*> ForceLocalSymbolTable;
- typedef std::vector<LDSymbol*> OutputSymbolTable;
+
+ /// checkIsOutputPIC - return whether the output is position-independent,
+ /// called by isOutputPIC()
+ bool checkIsOutputPIC() const;
+
+ /// checkIsStaticLink - return whether we're doing static link, called by
+ /// isStaticLink()
+ bool checkIsStaticLink() const;
+
+ /// 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;
- MCLDInfo& m_LDInfo;
- SectionMap& m_SectionMap;
- LDSymbolFactory m_LDSymbolFactory;
- LDSectionFactory m_LDSectHdrFactory;
- LDSectionDataFactory m_LDSectDataFactory;
- SectionMerger* m_pSectionMerger;
- Layout m_Layout;
- RelocationListType m_RelocationList;
- SymbolCategory m_OutputSymbols;
};
-#include "MCLinker.tcc"
+#include "FragmentLinker.tcc"
} // namespace of mcld
diff --git a/include/mcld/MC/MCLinker.tcc b/include/mcld/Fragment/FragmentLinker.tcc
similarity index 67%
rename from include/mcld/MC/MCLinker.tcc
rename to include/mcld/Fragment/FragmentLinker.tcc
index b13e48d..884a597 100644
--- a/include/mcld/MC/MCLinker.tcc
+++ b/include/mcld/Fragment/FragmentLinker.tcc
@@ -1,4 +1,4 @@
-//===- MCLinker.tcc -------------------------------------------------------===//
+//===- FragmentLinker.tcc --------------------------------------------------===//
//
// The MCLinker Project
//
@@ -9,21 +9,21 @@
/// addSymbol - add a symbol and resolve it immediately
template<Input::Type FROM>
-LDSymbol* MCLinker::addSymbol(const llvm::StringRef& pName,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility)
+LDSymbol* FragmentLinker::addSymbol(const llvm::StringRef& pName,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBinding,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
+ FragmentRef* pFragmentRef,
+ ResolveInfo::Visibility pVisibility)
{
llvm::StringRef symbol_name = pName;
if (!getLDInfo().scripts().renameMap().empty() &&
ResolveInfo::Undefined == pDesc) {
// If the renameMap is not empty, some symbols should be renamed.
// --wrap and --portable defines the symbol rename map.
- ScriptOptions::SymbolRenameMap::iterator renameSym
+ ScriptOptions::SymbolRenameMap::const_iterator renameSym
= getLDInfo().scripts().renameMap().find(pName);
if (renameSym != getLDInfo().scripts().renameMap().end())
symbol_name = renameSym.getEntry()->value();
@@ -54,20 +54,21 @@
}
// defineSymbol - define a new symbol
-template<MCLinker::DefinePolicy POLICY, MCLinker::ResolvePolicy RESOLVE>
-LDSymbol* MCLinker::defineSymbol(const llvm::StringRef& pName,
- bool pIsDyn,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility)
+template<FragmentLinker::DefinePolicy POLICY,
+ FragmentLinker::ResolvePolicy RESOLVE>
+LDSymbol* FragmentLinker::defineSymbol(const llvm::StringRef& pName,
+ bool pIsDyn,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBinding,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
+ FragmentRef* pFragmentRef,
+ ResolveInfo::Visibility pVisibility)
{
// These if/return should be optimized by compiler.
// This function is defined for clarity.
- if (MCLinker::Force == POLICY && MCLinker::Unresolve == RESOLVE)
+ if (FragmentLinker::Force == POLICY && FragmentLinker::Unresolve == RESOLVE)
return defineSymbolForcefully(pName,
pIsDyn,
pType,
@@ -78,7 +79,7 @@
pFragmentRef,
pVisibility);
- if (MCLinker::AsRefered == POLICY && MCLinker::Unresolve == RESOLVE)
+ if (FragmentLinker::AsRefered == POLICY && FragmentLinker::Unresolve == RESOLVE)
return defineSymbolAsRefered(pName,
pIsDyn,
pType,
@@ -89,7 +90,7 @@
pFragmentRef,
pVisibility);
- if (MCLinker::Force == POLICY && MCLinker::Resolve == RESOLVE)
+ if (FragmentLinker::Force == POLICY && FragmentLinker::Resolve == RESOLVE)
return defineAndResolveSymbolForcefully(pName,
pIsDyn,
pType,
@@ -100,7 +101,7 @@
pFragmentRef,
pVisibility);
- if (MCLinker::AsRefered == POLICY && MCLinker::Resolve == RESOLVE)
+ if (FragmentLinker::AsRefered == POLICY && FragmentLinker::Resolve == RESOLVE)
return defineAndResolveSymbolAsRefered(pName,
pIsDyn,
pType,
diff --git a/include/mcld/LD/FragmentRef.h b/include/mcld/Fragment/FragmentRef.h
similarity index 62%
rename from include/mcld/LD/FragmentRef.h
rename to include/mcld/Fragment/FragmentRef.h
index 20b94c2..3fce7c9 100644
--- a/include/mcld/LD/FragmentRef.h
+++ b/include/mcld/Fragment/FragmentRef.h
@@ -6,25 +6,23 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_FRAGMENT_REFERENCE_H
-#define MCLD_LD_FRAGMENT_REFERENCE_H
+#ifndef MCLD_FRAGMENT_FRAGMENT_REFERENCE_H
+#define MCLD_FRAGMENT_FRAGMENT_REFERENCE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
+#include <mcld/Config/Config.h>
#include <mcld/ADT/SizeTraits.h>
#include <mcld/ADT/TypeTraits.h>
-#include <mcld/LD/Fragment.h>
+#include <mcld/Support/Allocators.h>
-namespace mcld
-{
+namespace mcld {
+class Fragment;
+class LDSection;
class Layout;
-/// compunteFragmentSize - compute the specific Fragment size
-uint64_t computeFragmentSize(const Layout& pLayout,
- const Fragment& pFrag);
-
/** \class FragmentRef
* \brief FragmentRef is a reference of a Fragment's contetnt.
*
@@ -37,9 +35,21 @@
typedef ConstTraits<unsigned char>::pointer ConstAddress;
public:
- FragmentRef();
- FragmentRef(Fragment& pFrag, Offset pOffset = 0);
- ~FragmentRef();
+ /// Create - create a fragment reference for a given fragment.
+ ///
+ /// @param pFrag - the given fragment
+ /// @param pOffset - the offset, can be larger than the fragment, but can not
+ /// be larger than the section size.
+ /// @return if the offset is legal, return the fragment reference. Otherwise,
+ /// return NULL.
+ static FragmentRef* Create(Fragment& pFrag, uint64_t pOffset);
+
+ static FragmentRef* Create(LDSection& pSection, uint64_t pOffset);
+
+ /// Clear - clear all generated FragmentRef in the system.
+ static void Clear();
+
+ static FragmentRef* Null();
// ----- modifiers ----- //
FragmentRef& assign(const FragmentRef& pCopy);
@@ -55,6 +65,8 @@
void memcpy(void* pDest, size_t pNBytes, Offset pOffset = 0) const;
// ----- observers ----- //
+ bool isNull() const { return (this == Null()); }
+
Fragment* frag()
{ return m_pFragment; }
@@ -64,6 +76,8 @@
Offset offset() const
{ return m_Offset; }
+ Offset getOutputOffset() const;
+
// ----- dereference ----- //
Address deref();
@@ -74,10 +88,22 @@
ConstAddress operator*() const
{ return deref(); }
+
+private:
+ friend FragmentRef& NullFragmentRef();
+ friend class Chunk<FragmentRef, MCLD_SECTIONS_PER_INPUT>;
+ friend class Relocation;
+
+ FragmentRef();
+
+ FragmentRef(Fragment& pFrag, Offset pOffset = 0);
private:
Fragment* m_pFragment;
Offset m_Offset;
+
+ static FragmentRef g_NullFragmentRef;
+
};
} // namespace of mcld
diff --git a/include/mcld/Fragment/NullFragment.h b/include/mcld/Fragment/NullFragment.h
new file mode 100644
index 0000000..1c84fae
--- /dev/null
+++ b/include/mcld/Fragment/NullFragment.h
@@ -0,0 +1,43 @@
+//===- NullFragment.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_LD_NULL_FRAGMENT_H
+#define MCLD_LD_NULL_FRAGMENT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Fragment/Fragment.h>
+
+namespace mcld {
+
+class SectionData;
+
+/** \class NullFragment
+ * \brief NullFragment is a kind of MCFragment that presents the "end fragment"
+ * referenced by some special symbols
+ */
+class NullFragment : public Fragment
+{
+public:
+ NullFragment(SectionData* pSD = NULL);
+
+ /// size -
+ size_t size() const { return 0x0; }
+
+ static bool classof(const Fragment *F)
+ { return F->getKind() == Fragment::Null; }
+
+ static bool classof(const NullFragment *)
+ { return true; }
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/RegionFragment.h b/include/mcld/Fragment/RegionFragment.h
similarity index 80%
rename from include/mcld/LD/RegionFragment.h
rename to include/mcld/Fragment/RegionFragment.h
index 8aba1ef..e077264 100644
--- a/include/mcld/LD/RegionFragment.h
+++ b/include/mcld/Fragment/RegionFragment.h
@@ -6,18 +6,17 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#ifndef MCLD_LD_REGION_FRAGMENT_H
#define MCLD_LD_REGION_FRAGMENT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <mcld/LD/Fragment.h>
-#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Fragment/Fragment.h>
-namespace mcld
-{
+namespace mcld {
+
+class MemoryRegion;
/** \class RegionFragment
* \brief RegionFragment is a kind of Fragment containing mcld::MemoryRegion
@@ -29,11 +28,8 @@
~RegionFragment();
- MemoryRegion& getRegion()
- { return m_Region; }
-
- const MemoryRegion& getRegion() const
- { return m_Region; }
+ const MemoryRegion& getRegion() const { return m_Region; }
+ MemoryRegion& getRegion() { return m_Region; }
static bool classof(const Fragment *F)
{ return F->getKind() == Fragment::Region; }
@@ -41,6 +37,8 @@
static bool classof(const RegionFragment *)
{ return true; }
+ size_t size() const;
+
private:
MemoryRegion& m_Region;
};
diff --git a/include/mcld/LD/Relocation.h b/include/mcld/Fragment/Relocation.h
similarity index 68%
rename from include/mcld/LD/Relocation.h
rename to include/mcld/Fragment/Relocation.h
index fa77e64..c6584c4 100644
--- a/include/mcld/LD/Relocation.h
+++ b/include/mcld/Fragment/Relocation.h
@@ -6,25 +6,21 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_RELOCATION_H
-#define MCLD_LD_RELOCATION_H
+#ifndef MCLD_FRAGMENT_RELOCATION_H
+#define MCLD_FRAGMENT_RELOCATION_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <llvm/ADT/ilist_node.h>
#include <llvm/Support/DataTypes.h>
-#include <mcld/LD/Fragment.h>
-#include <mcld/LD/FragmentRef.h>
-#include <mcld/LD/ResolveInfo.h>
-#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Fragment.h>
+#include <mcld/Fragment/FragmentRef.h>
+namespace mcld {
-namespace mcld
-{
-class Layout;
+class ResolveInfo;
class RelocationFactory;
-class MCLDInfo;
+class LinkerConfig;
class Relocation : public Fragment
{
@@ -33,6 +29,7 @@
public:
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;
private:
@@ -56,31 +53,26 @@
{ return m_Addend; }
/// place - P value - address of the place being relocated
- Address place(const Layout& pLayout) const;
+ Address place() const;
/// symbol info - binding, type
- const ResolveInfo* symInfo() const
- { return m_pSymInfo; }
-
- /// symbol info - binding, type
- ResolveInfo* symInfo()
- { return m_pSymInfo; }
+ const ResolveInfo* symInfo() const { return m_pSymInfo; }
+ ResolveInfo* symInfo() { return m_pSymInfo; }
/// target - the target data to relocate
- DWord& target();
-
- /// target - the target data to relocate
- const DWord& target() const;
+ const DWord& target() const { return m_TargetData; }
+ DWord& target() { return m_TargetData; }
/// targetRef - the reference of the target data
- FragmentRef& targetRef()
- { return m_TargetAddress; }
+ const FragmentRef& targetRef() const { return m_TargetAddress; }
+ FragmentRef& targetRef() { return m_TargetAddress; }
- /// targetRef - the reference of the target data
- const FragmentRef& targetRef() const
- { return m_TargetAddress; }
- void apply(RelocationFactory& pRelocFactory, const MCLDInfo& pLDInfo);
+ void apply(RelocationFactory& pRelocFactory);
+
+ /// updateAddend - A relocation with a section symbol must update addend
+ /// before reading its value.
+ void updateAddend();
/// ----- modifiers ----- ///
void setType(Type pType);
@@ -92,7 +84,11 @@
// Relocation is a kind of Fragment with type of FT_Reloc
static bool classof(const Fragment *F)
{ return F->getKind() == Fragment::Relocation; }
- static bool classof(const Relocation *) { return true; }
+
+ static bool classof(const Relocation *)
+ { return true; }
+
+ size_t size() const;
private:
/// m_Type - the type of the relocation entries
diff --git a/include/mcld/Fragment/Stub.h b/include/mcld/Fragment/Stub.h
new file mode 100644
index 0000000..11a1db4
--- /dev/null
+++ b/include/mcld/Fragment/Stub.h
@@ -0,0 +1,134 @@
+//===- Stub.h -------------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MCLD_FRAGMENT_STUB_H
+#define MCLD_FRAGMENT_STUB_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/Fragment/Fragment.h>
+#include <mcld/Fragment/Relocation.h>
+#include <vector>
+#include <string>
+
+namespace mcld
+{
+
+class Relocation;
+class ResolveInfo;
+
+class Stub: public Fragment
+{
+public:
+ typedef Relocation::DWord DWord;
+ typedef Relocation::SWord SWord;
+ typedef Relocation::Type Type;
+
+ class Fixup
+ {
+ public:
+ Fixup(DWord pOffset, SWord pAddend, Type pType)
+ : m_Offset(pOffset), m_Addend(pAddend), m_Type(pType)
+ { }
+
+ ~Fixup()
+ { }
+
+ DWord offset() const { return m_Offset; }
+
+ SWord addend() const { return m_Addend; }
+
+ Type type() const { return m_Type; }
+
+ private:
+ DWord m_Offset;
+ SWord m_Addend;
+ Type m_Type;
+ };
+
+public:
+ typedef std::vector<Fixup*> FixupListType;
+ typedef FixupListType::iterator fixup_iterator;
+ typedef FixupListType::const_iterator const_fixup_iterator;
+
+public:
+ Stub();
+
+ virtual ~Stub();
+
+ /// clone - clone function for stub factory to create the corresponding stub
+ Stub* clone() { return doClone(); }
+
+ /// isMyDuty - return true when the pReloc is problematic and the stub is able
+ /// to fix it!
+ virtual bool isMyDuty(const class Relocation& pReloc,
+ uint64_t pSource,
+ uint64_t pTargetSymValue) const = 0;
+
+ /// name - name of this stub
+ virtual const std::string& name() const = 0;
+
+ /// getContent - content of the stub
+ virtual const uint8_t* getContent() const = 0;
+
+ /// size - size of the stub
+ virtual size_t size() const = 0;
+
+ /// alignment - alignment of the stub
+ virtual size_t alignment() const = 0;
+
+ /// symInfo - ResolveInfo of this Stub
+ ResolveInfo* symInfo() { return m_pSymInfo; }
+
+ const ResolveInfo* symInfo() const { return m_pSymInfo; }
+
+ /// symValue - initial value for stub's symbol
+ virtual uint64_t initSymValue() const { return 0x0; }
+
+ /// ----- Fixup ----- ///
+ fixup_iterator fixup_begin() { return m_FixupList.begin(); }
+
+ const_fixup_iterator fixup_begin() const { return m_FixupList.begin(); }
+
+ fixup_iterator fixup_end() { return m_FixupList.end(); }
+
+ const_fixup_iterator fixup_end() const { return m_FixupList.end(); }
+
+ /// ----- modifiers ----- ///
+ void setSymInfo(ResolveInfo* pSymInfo);
+
+ // Stub is a kind of Fragment with type of Stub
+ static bool classof(const Fragment *F)
+ { return F->getKind() == Fragment::Stub; }
+
+ static bool classof(const Stub *)
+ { return true; }
+
+protected:
+ /// addFixup - add a fixup for this stub to build a relocation
+ void addFixup(DWord pOffset, SWord pAddend, Type pType);
+
+ /// addFixup - add a fixup from a existing fixup of the prototype
+ void addFixup(const Fixup& pFixup);
+
+private:
+ /// doClone - when adding a backend stub, we should implement this function
+ virtual Stub* doClone() = 0;
+
+private:
+ ResolveInfo* m_pSymInfo;
+ FixupListType m_FixupList;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/TargetFragment.h b/include/mcld/Fragment/TargetFragment.h
similarity index 90%
rename from include/mcld/LD/TargetFragment.h
rename to include/mcld/Fragment/TargetFragment.h
index 92af5a0..665fcea 100644
--- a/include/mcld/LD/TargetFragment.h
+++ b/include/mcld/Fragment/TargetFragment.h
@@ -6,17 +6,15 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#ifndef MCLD_LD_TARGET_FRAGMENT_H
#define MCLD_LD_TARGET_FRAGMENT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <mcld/LD/Fragment.h>
+#include <mcld/Fragment/Fragment.h>
-namespace mcld
-{
+namespace mcld {
class SectionData;
@@ -33,9 +31,6 @@
public:
virtual ~TargetFragment() {}
- virtual size_t getSize() const = 0;
-
-public:
static bool classof(const Fragment *F)
{ return F->getKind() == Fragment::Target; }
diff --git a/include/mcld/MC/MCLDOptions.h b/include/mcld/GeneralOptions.h
similarity index 78%
rename from include/mcld/MC/MCLDOptions.h
rename to include/mcld/GeneralOptions.h
index ad857cb..0b5c7a9 100644
--- a/include/mcld/MC/MCLDOptions.h
+++ b/include/mcld/GeneralOptions.h
@@ -1,4 +1,4 @@
-//===- MCLDOptions.h ------------------------------------------------------===//
+//===- GeneralOptions.h ---------------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,48 +6,21 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_OPTIONS_H
-#define MCLD_OPTIONS_H
+#ifndef MCLD_GENERAL_OPTIONS_H
+#define MCLD_GENERAL_OPTIONS_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <string>
-#include <llvm/ADT/StringRef.h>
-#include <mcld/ADT/StringEntry.h>
-#include <mcld/ADT/HashTable.h>
#include <mcld/Support/RealPath.h>
#include <mcld/Support/FileSystem.h>
#include <mcld/MC/SearchDirs.h>
#include <mcld/MC/ZOption.h>
-namespace mcld
-{
+namespace mcld {
+
class Input;
-/** \class ScriptOptions
- *
- */
-class ScriptOptions
-{
-public:
- typedef HashTable<StringEntry<llvm::StringRef>,
- StringHash<ELF>,
- StringEntryFactory<llvm::StringRef> > SymbolRenameMap;
-
-public:
- ScriptOptions();
- ~ScriptOptions();
-
- SymbolRenameMap& renameMap()
- { return m_SymbolRenames; }
-
- const SymbolRenameMap& renameMap() const
- { return m_SymbolRenames; }
-
-private:
- SymbolRenameMap m_SymbolRenames;
-};
-
/** \class GeneralOptions
* \brief GeneralOptions collects the options that not be one of the
* - input files
@@ -66,8 +39,7 @@
void setDefaultLDScript(const std::string& pFilename);
/// sysroot
- const sys::fs::Path& sysroot() const
- { return m_Sysroot; }
+ const sys::fs::Path& sysroot() const;
void setSysroot(const sys::fs::Path &pPath);
@@ -85,7 +57,7 @@
bool trace() const
{ return m_bTrace; }
- void setBsymbolic(bool pBsymbolic = false)
+ void setBsymbolic(bool pBsymbolic = true)
{ m_Bsymbolic = pBsymbolic; }
bool Bsymbolic() const
@@ -97,7 +69,7 @@
bool isPIE() const
{ return m_bPIE; }
- void setBgroup(bool pBgroup = false)
+ void setBgroup(bool pBgroup = true)
{ m_Bgroup = pBgroup; }
bool Bgroup() const
@@ -121,6 +93,11 @@
bool hasDyld() const
{ return !m_Dyld.empty(); }
+ void setSOName(const std::string& pName);
+
+ const std::string& soname() const
+ { return m_SOName; }
+
void setAllowShlibUndefined(bool pEnabled = true)
{ m_bAllowShlibUndefined = pEnabled; }
@@ -151,10 +128,10 @@
bool color() const
{ return m_bColor; }
- void setNoUndefined(bool pEnable = false)
+ void setNoUndefined(bool pEnable = true)
{ m_bNoUndefined = pEnable; }
- void setMulDefs(bool pEnable = false)
+ void setMulDefs(bool pEnable = true)
{ m_bMulDefs = pEnable; }
void setEhFrameHdr(bool pEnable = true)
@@ -220,6 +197,41 @@
bool hasEhFrameHdr() const
{ return m_bCreateEhFrameHdr; }
+ // -n, --nmagic
+ void setNMagic(bool pMagic = true)
+ { m_NMagic = pMagic; }
+
+ bool nnagic() const
+ { return m_NMagic; }
+
+ // -N, --omagic
+ void setOMagic(bool pMagic = true)
+ { m_OMagic = pMagic; }
+
+ bool omagic() const
+ { return m_OMagic; }
+
+ // -S, --strip-debug
+ void setStripDebug(bool pStripDebug = true)
+ { m_StripDebug = pStripDebug; }
+
+ bool stripDebug() const
+ { return m_StripDebug; }
+
+ // -E, --export-dynamic
+ void setExportDynamic(bool pExportDynamic = true)
+ { m_ExportDynamic = pExportDynamic; }
+
+ bool exportDynamic() const
+ { return m_ExportDynamic; }
+
+ // --warn-shared-textrel
+ void setWarnSharedTextrel(bool pWarnSharedTextrel = true)
+ { m_WarnSharedTextrel = pWarnSharedTextrel; }
+
+ bool warnSharedTextrel() const
+ { return m_WarnSharedTextrel; }
+
private:
enum status {
YES,
@@ -230,10 +242,10 @@
private:
Input* m_pDefaultBitcode;
std::string m_DefaultLDScript;
- sys::fs::RealPath m_Sysroot;
SearchDirs m_SearchDirs;
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
@@ -261,6 +273,11 @@
bool m_bColor : 1; // --color[=true,false,auto]
bool m_bAllowShlibUndefined : 1; // --[no-]allow-shlib-undefined and
bool m_bCreateEhFrameHdr : 1; // --eh-frame-hdr
+ bool m_NMagic; // -n, --nmagic
+ bool m_OMagic; // -N, --omagic
+ bool m_StripDebug; // -S, --strip-debug
+ bool m_ExportDynamic; //-E, --export-dynamic
+ bool m_WarnSharedTextrel; // --warn-shared-textrel
};
} // namespace of mcld
diff --git a/include/mcld/IRBuilder.h b/include/mcld/IRBuilder.h
new file mode 100644
index 0000000..1ebd153
--- /dev/null
+++ b/include/mcld/IRBuilder.h
@@ -0,0 +1,372 @@
+//===- IRBuilder.h --------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// IRBuilder is a class used as a convenient way to create MCLinker sections
+// with a consistent and simplified interface.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_IRBUILDER_H
+#define MCLD_IRBUILDER_H
+
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/InputBuilder.h>
+
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/EhFrame.h>
+
+#include <mcld/Fragment/Fragment.h>
+#include <mcld/Fragment/Relocation.h>
+#include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Fragment/FillFragment.h>
+
+#include <mcld/Support/Path.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/raw_mem_ostream.h>
+
+namespace mcld {
+
+class Module;
+class LinkerConfig;
+class InputTree;
+
+/** \class IRBuilder
+ * \brief IRBuilder provides an uniform API for creating sections and
+ * inserting them into a input file.
+ *
+ * Ahead-of-time virtual machines (VM) usually compiles an intermediate
+ * language into a system-dependent binary. IRBuilder helps such kind of VMs
+ * to emit binaries in native object format, such as ELF or MachO.
+ */
+class IRBuilder
+{
+public:
+ enum ObjectFormat {
+ ELF,
+ MachO,
+ COFF
+ };
+
+public:
+ IRBuilder(Module& pModule, const LinkerConfig& pConfig);
+
+ ~IRBuilder();
+
+ const InputBuilder& getInputBuilder() const { return m_InputBuilder; }
+ InputBuilder& getInputBuilder() { return m_InputBuilder; }
+
+/// @}
+/// @name Input Files On The Command Line
+/// @{
+
+ /// CreateInput - To create an input file and append it to the input tree.
+ /// This function is like to add an input file in the command line.
+ ///
+ /// There are four types of the input files:
+ /// - relocatable objects,
+ /// - shared objects,
+ /// - archives,
+ /// - and user-defined objects.
+ ///
+ /// If Input::Unknown type is given, MCLinker will automatically
+ /// open and read the input file, and create sections of the input. Otherwise,
+ /// users need to manually create sections by IRBuilder.
+ ///
+ /// @see mcld::Input
+ ///
+ /// @param pName [in] The name of the input file.
+ /// @param pPath [in] The path of the input file.
+ /// @param pType [in] The type of the input file. MCLinker will parse the
+ /// input file to create sections only if pType is
+ /// Input::Unknown.
+ /// @return the created mcld::Input.
+ Input* CreateInput(const std::string& pName,
+ const sys::fs::Path& pPath,
+ Input::Type pType);
+
+ /// ReadInput - To read an input file and append it to the input tree.
+ /// This function is like to add an input file in the command line.
+ ///
+ /// This funciton is equal to call
+ /// @ref IRBuilder::CreateInput(pName, pPath, Input::Unknown);
+ ///
+ /// MCLinker will automatically open and read the input file, and create
+ /// sections of the input.
+ ///
+ /// @see mcld::Input
+ ///
+ /// @param pName [in] The name of the input file.
+ /// @param pPath [in] The path of the input file.
+ /// @return the created mcld::Input.
+ Input* ReadInput(const std::string& pName, const sys::fs::Path& pPath);
+
+ /// ReadInput - To read an input file and append it to the input tree.
+ ///
+ /// This function is equal to -l option. This function tells MCLinker to
+ /// search for lib[pNameSpec].so or lib[pNameSpec].a in the search path.
+ ///
+ /// @param pNameSpec [in] The namespec of the input file.
+ /// @return the created mcld::Input.
+ 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);
+
+ /// 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.
+ ///
+ /// This function tells MCLinker to read pRawMemory as an image of an object
+ /// file. So far, MCLinekr only supports ELF object format, but it will
+ /// support various object formats in the future. MCLinker relies triple to
+ /// know the object format of pRawMemory.
+ /// @param [in] pName The name of the input file
+ /// @param [in] pRawMemory An image of object file
+ /// @param [in] pSize The size of the memory
+ /// @return The created mcld::Input
+ Input* ReadInput(const std::string& pName, void* pRawMemory, size_t pSize);
+
+ /// StartGroup - Add an opening tag of group.
+ ///
+ /// This function is equal to --start-group option. This function tells
+ /// MCLinker to create a new archive group and to add the following archives
+ /// in the created group. The archives in a group are searched repeatedly
+ /// until no new undefined references are created.
+ bool StartGroup();
+
+ /// EndGroup - Add a closing tag of group.
+ ///
+ /// This function is equal to --end-group option. This function tells
+ /// MCLinker to stop adding following archives in the created group.
+ bool EndGroup();
+
+/// @}
+/// @name Positional Options On The Command Line
+/// @{
+
+ /// WholeArchive - Append a --whole-archive option on the command line
+ ///
+ /// This function is equal to --whole-archive option. This function tells
+ /// MCLinker to include every object files in the following archives.
+ void WholeArchive();
+
+ /// NoWholeArchive - Append a --no-whole-archive option on the command line.
+ ///
+ /// This function is equal to --no-whole-archive option. This function tells
+ /// MCLinker to stop including every object files in the following archives.
+ /// Only used object files in the following archives are included.
+ void NoWholeArchive();
+
+ /// AsNeeded - Append a --as-needed option on the command line.
+ ///
+ /// This function is equal to --as-needed option. This function tells
+ /// MCLinker to not add a DT_NEEDED tag in .dynamic sections for the
+ /// following shared objects that are not really used. MCLinker will add tags
+ // only for the following shared objects which is really used.
+ void AsNeeded();
+
+ /// NoAsNeeded - Append a --no-as-needed option on the command line.
+ ///
+ /// This function is equal to --no-as-needed option. This function tells
+ /// MCLinker to add a DT_NEEDED tag in .dynamic section for every shared
+ /// objects that is created after this option.
+ void NoAsNeeded();
+
+ /// CopyDTNeeded - Append a --add-needed option on the command line.
+ ///
+ /// This function is equal to --add-needed option. This function tells
+ /// NCLinker to copy all DT_NEEDED tags of every following shared objects
+ /// to the output file.
+ void CopyDTNeeded();
+
+ /// NoCopyDTNeeded - Append a --no-add-needed option on the command line.
+ ///
+ /// This function is equal to --no-add-needed option. This function tells
+ /// MCLinker to stop copying all DT_NEEDS tags in the following shared
+ /// objects to the output file.
+ void NoCopyDTNeeded();
+
+ /// AgainstShared - Append a -Bdynamic option on the command line.
+ ///
+ /// This function is equal to -Bdynamic option. This function tells MCLinker
+ /// to search shared objects before archives for the following namespec.
+ void AgainstShared();
+
+ /// AgainstStatic - Append a -static option on the command line.
+ ///
+ /// This function is equal to -static option. This function tells MCLinker to
+ /// search archives before shared objects for the following namespec.
+ void AgainstStatic();
+
+/// @}
+/// @name Input Methods
+/// @{
+
+ /// CreateELFHeader - To create and append a section header in the input file
+ ///
+ /// @param OF [in] The file format. @see ObjectFormat
+ /// @param pInput [in, out] The input file.
+ /// @param pName [in] The name of the section.
+ /// @param pType [in] The meaning of the content in the section. The
+ /// value is format-dependent. In ELF, the value is
+ /// SHT_* in normal.
+ /// @param pFlag [in] The format-dependent flag. In ELF, the value is
+ /// SHF_* in normal.
+ /// @param pAlign [in] The alignment constraint of the section
+ /// @return The created section header.
+ static LDSection* CreateELFHeader(Input& pInput,
+ const std::string& pName,
+ uint32_t pType,
+ uint32_t pFlag,
+ uint32_t pAlign);
+
+ /// CreateSectionData - To create a section data for given pSection.
+ /// @param [in, out] pSection The given LDSection. It can be in either an
+ /// input or the output.
+ /// pSection.getSectionData() is set to a valid section data.
+ /// @return The created section data. If the pSection already has section
+ /// data, or if the pSection's type should not have a section data
+ /// (.eh_frame or relocation data), then an assertion occurs.
+ static SectionData* CreateSectionData(LDSection& pSection);
+
+ /// CreateRelocData - To create a relocation data for given pSection.
+ /// @param [in, out] pSection The given LDSection. It can be in either an
+ /// input or the output.
+ /// pSection.getRelocData() is set to a valid relocation data.
+ /// @return The created relocation data. If the pSection already has
+ /// relocation data, or if the pSection's type is not
+ /// LDFileFormat::Relocation, then an assertion occurs.
+ static RelocData* CreateRelocData(LDSection &pSection);
+
+ /// CreateEhFrame - To create a eh_frame for given pSection
+ /// @param [in, out] pSection The given LDSection. It can be in either an
+ /// input or the output.
+ /// pSection.getEhFrame() is set to a valid eh_frame.
+ /// @return The created eh_frame. If the pSection already has eh_frame data,
+ /// or if the pSection's type is not LDFileFormat::EhFrame, then an
+ /// assertion occurs.
+ static EhFrame* CreateEhFrame(LDSection& pSection);
+
+ /// CreateBSS - To create a bss section for given pSection
+ /// @param [in, out] pSection The given LDSection. It can be in either an
+ /// input or the output.
+ /// pSection.getSectionData() is set to a valid section data and
+ /// contains a fillment fragment whose size is pSection.size().
+ /// @return The create section data. It the pSection already has a section
+ /// data, or if the pSection's type is not LDFileFormat::BSS, then
+ /// an assertion occurs.
+ static SectionData* CreateBSS(LDSection& pSection);
+
+ /// CreateRegion - To create a region fragment in the input file.
+ /// This function tells MCLinker to read a piece of data from the input
+ /// file, and to create a region fragment that carries the data. The data
+ /// will be deallocated automatically when pInput is destroyed.
+ ///
+ /// @param pInput [in, out] The input file.
+ /// @param pOffset [in] The starting file offset of the data
+ /// @param pLength [in] The number of bytes of the data
+ /// @return If pLength is zero or failing to request a region, return a
+ /// FillFragment.
+ static Fragment* CreateRegion(Input& pInput, size_t pOffset, size_t pLength);
+
+ /// CreateRegion - To create a region fragment wrapping the given memory.
+ /// This function tells MCLinker to create a region fragment by the data
+ /// directly. Since the data is given from outside, not read from the input
+ /// file, users should deallocated the data manually.
+ ///
+ /// @param pMemory [in] The start address of the given data
+ /// @param pLength [in] The number of bytes of the data
+ /// @return If pLength is zero or failing to request a region, return a
+ /// FillFragment.
+ static Fragment* CreateRegion(void* pMemory, size_t pLength);
+
+ /// AppendFragment - To append pFrag to the given SectionData pSD.
+ /// This function tells MCLinker to append a fragment to section data, and
+ /// update size of the section header.
+ ///
+ /// @note In order to keep the alignment of pFrag, This function inserts an
+ /// AlignFragment before pFrag if the section header's alignment is larger
+ /// than 1.
+ /// @note This function does not update offset of section headers.
+ ///
+ /// @param pFrag [in, out] The appended fragment. Its offset is set as the
+ /// section offset in pSD.
+ /// @param pSD [in, out] The section data. Size of the header is also
+ /// updated.
+ /// @return Total size of the inserted fragments.
+ static uint64_t AppendFragment(Fragment& pFrag, SectionData& pSD);
+
+ /// AppendRelocation - To append a relocation to a relocation data.
+ /// This function tells MCLinker to add a general relocation to the
+ /// relocation data. This function does not update offset and size of section
+ /// headers.
+ ///
+ /// @param pReloc [in] The appended relocation.
+ /// @param pRD [in, out] The relocation data being appended.
+ static void AppendRelocation(Relocation& pRelocation, RelocData& pRD);
+
+ /// AppendEhFrame - To append a fragment to a EhFrame.
+ /// @note In order to keep the alignment of pFrag, This function inserts an
+ /// AlignFragment before pFrag if the section header's alignment is larger
+ /// than 1.
+ /// @note This function also update size of the section header, but does not
+ /// update header's offset.
+ ///
+ /// @param pFrag [in, out] The appended fragment.
+ /// @param pEhFrame [in, out] The EhFrame.
+ /// @return Total size of the inserted fragments.
+ static uint64_t AppendEhFrame(Fragment& pFrag, EhFrame& pEhFrame);
+
+ /// AppendEhFrame - To append a FDE to the given EhFrame pEhFram.
+ /// @note In order to keep the alignment of pFrag, This function inserts an
+ /// AlignFragment before pFrag if the section header's alignment is larger
+ /// than 1.
+ /// @note This function also update size of the section header, but does not
+ /// update header's offset.
+ ///
+ /// @param [in, out] pFDE The appended FDE entry.
+ /// @param [in, out] pEhFrame The eh_frame being appended.
+ /// @return Total size of the inserted fragments.
+ static uint64_t AppendEhFrame(EhFrame::FDE& pFDE, EhFrame& pEhFrame);
+
+ /// AppendEhFrame - To append a CIE to the given EhFrame pEhFram.
+ /// @note In order to keep the alignment of pFrag, This function inserts an
+ /// AlignFragment before pFrag if the section header's alignment is larger
+ /// than 1.
+ /// @note This function also update size of the section header, but does not
+ /// update header's offset.
+ ///
+ /// @param [in, out] pCIE The appended CIE entry.
+ /// @param [in, out] pEhFrame The eh_frame being appended.
+ /// @return Total size of the inserted fragments.
+ static uint64_t AppendEhFrame(EhFrame::CIE& pCIE, EhFrame& pEhFrame);
+
+private:
+ Module& m_Module;
+ const LinkerConfig& m_Config;
+
+ InputBuilder m_InputBuilder;
+};
+
+} // end of namespace mcld
+
+#endif
diff --git a/include/mcld/MC/InputTree.h b/include/mcld/InputTree.h
similarity index 70%
rename from include/mcld/MC/InputTree.h
rename to include/mcld/InputTree.h
index 5916916..2981ebe 100644
--- a/include/mcld/MC/InputTree.h
+++ b/include/mcld/InputTree.h
@@ -6,23 +6,21 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_INPUT_TREE_H
-#define MCLD_INPUT_TREE_H
+#ifndef MCLD_MC_INPUT_TREE_H
+#define MCLD_MC_INPUT_TREE_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/InputFactory.h"
-#include "mcld/Support/FileSystem.h"
+#include <mcld/ADT/BinTree.h>
+#include <mcld/ADT/TypeTraits.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/Support/Path.h>
#include <string>
-namespace mcld
-{
+namespace mcld {
/** \class template<typename Traits, typename Iterator> PolicyIterator<mcld::Input>
* \brief PolicyIterator<mcld::Input> is a partially specific PolicyIterator
@@ -49,11 +47,12 @@
virtual ~PolicyIterator() {}
bool isGroup() const
- { return !Base::hasData(); }
+ { return !Base::hasData() && !Base::isRoot(); }
Self& operator++() {
IteratorType::advance();
- if (isGroup())
+ // skip the Group node
+ while (isGroup())
IteratorType::advance();
return *this;
}
@@ -61,7 +60,8 @@
Self operator++(int) {
Self tmp(*this);
IteratorType::advance();
- if (isGroup())
+ // skip the Group node
+ while (isGroup())
IteratorType::advance();
return tmp;
}
@@ -137,54 +137,25 @@
using BinTreeTy::merge;
- InputTree(InputFactory& pInputFactory);
- ~InputTree();
-
// ----- modify ----- //
- /// insert - create a leaf node and merge it in the tree.
- // This version of join determines the direction at run time.
- // @param pRoot position the parent node
- // @param pMover the direction of the connecting edge of the parent node.
- template<size_t DIRECT>
- InputTree& insert(TreeIteratorBase pRoot,
- const std::string& pNamespec,
- const sys::fs::Path& pPath,
- unsigned int pType = Input::Unknown);
-
template<size_t DIRECT>
InputTree& enterGroup(TreeIteratorBase pRoot);
template<size_t DIRECT>
InputTree& insert(TreeIteratorBase pRoot,
- const Input& pInput);
+ Input& pInput);
- InputTree& merge(TreeIteratorBase pRoot,
+ InputTree& merge(TreeIteratorBase pRoot,
const Mover& pMover,
InputTree& pTree);
InputTree& insert(TreeIteratorBase pRoot,
const Mover& pMover,
- const std::string& pNamespec,
- const sys::fs::Path& pPath,
- unsigned int pType = Input::Unknown);
-
- InputTree& insert(TreeIteratorBase pRoot,
- const Mover& pMover,
- const Input& pInput);
+ Input& pInput);
InputTree& enterGroup(TreeIteratorBase pRoot,
const Mover& pMover);
- // ----- observers ----- //
- unsigned int numOfInputs() const
- { return m_FileFactory.size(); }
-
- bool hasInput() const
- { return !m_FileFactory.empty(); }
-
-private:
- InputFactory& m_FileFactory;
-
};
bool isGroup(const InputTree::iterator& pos);
@@ -198,29 +169,12 @@
//===----------------------------------------------------------------------===//
// template member functions
-template<size_t DIRECT>
-mcld::InputTree&
-mcld::InputTree::insert(mcld::TreeIteratorBase pRoot,
- const std::string& pNamespec,
- const mcld::sys::fs::Path& pPath,
- unsigned int pType)
-{
- BinTreeTy::node_type* node = createNode();
- node->data = m_FileFactory.produce(pNamespec, pPath, pType);
- if (pRoot.isRoot())
- proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
- const_cast<const node_type*>(node));
- else
- proxy::hook<DIRECT>(pRoot.m_pNode,
- const_cast<const node_type*>(node));
- return *this;
-}
-
+//===----------------------------------------------------------------------===//
template<size_t DIRECT>
mcld::InputTree&
mcld::InputTree::enterGroup(mcld::TreeIteratorBase pRoot)
{
- BinTreeTy::node_type* node = createNode();
+ BinTreeTy::node_type* node = createNode();
if (pRoot.isRoot())
proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
const_cast<const node_type*>(node));
@@ -232,10 +186,10 @@
template<size_t DIRECT>
mcld::InputTree& mcld::InputTree::insert(mcld::TreeIteratorBase pRoot,
- const mcld::Input& pInput)
+ mcld::Input& pInput)
{
BinTreeTy::node_type* node = createNode();
- node->data = const_cast<mcld::Input*>(&pInput);
+ node->data = &pInput;
if (pRoot.isRoot())
proxy::hook<TreeIteratorBase::Leftward>(pRoot.m_pNode,
const_cast<const node_type*>(node));
diff --git a/include/mcld/LD/Archive.h b/include/mcld/LD/Archive.h
index 12b574c..53cf2a5 100644
--- a/include/mcld/LD/Archive.h
+++ b/include/mcld/LD/Archive.h
@@ -12,19 +12,23 @@
#include <gtest.h>
#endif
+#include <mcld/InputTree.h>
#include <mcld/ADT/HashEntry.h>
#include <mcld/ADT/HashTable.h>
#include <mcld/ADT/StringHash.h>
#include <mcld/Support/GCFactory.h>
-#include <mcld/MC/InputTree.h>
#include <vector>
#include <string>
-namespace mcld
-{
-class InputTree;
+namespace mcld {
+
class Input;
+class InputFactory;
+class InputBuilder;
+class AttributeFactory;
+class ContextFactory;
+class MemoryAreaFactory;
/** \class Archive
* \brief This class define the interfacee to Archive files
@@ -63,13 +67,12 @@
{
size_t operator()(uint32_t pKey) const
{
- size_t h;
- h ^= h >> 16;
- h *= 0x85ebca6b;
- h ^= h >> 13;
- h *= 0xc2b2ae35;
- h ^= h >> 16;
- return h;
+ pKey ^= pKey >> 16;
+ pKey *= 0x85ebca6b;
+ pKey ^= pKey >> 13;
+ pKey *= 0xc2b2ae35;
+ pKey ^= pKey >> 16;
+ return pKey;
}
};
@@ -126,7 +129,7 @@
typedef std::vector<Symbol*> SymTabType;
public:
- Archive(Input& pInputFile, InputFactory& pInputFactory);
+ Archive(Input& pInputFile, InputBuilder& pBuilder);
~Archive();
@@ -223,6 +226,21 @@
/// getStrTable - get the extended name table
const std::string& getStrTable() const;
+ /// hasStrTable - return true if this archive has extended name table
+ bool hasStrTable() const;
+
+ /// getMemberFile - get the member file in an archive member
+ /// @param pArchiveFile - Input reference of the archive member
+ /// @param pIsThinAR - denote the archive menber is a Thin Archive or not
+ /// @param pName - the name of the member file we want to get
+ /// @param pPath - the path of the member file
+ /// @param pFileOffset - the file offset of the member file in a regular AR
+ Input* getMemberFile(Input& pArchiveFile,
+ bool isThinAR,
+ const std::string& pName,
+ const sys::fs::Path& pPath,
+ off_t pFileOffset = 0);
+
private:
typedef GCFactory<Symbol, 0> SymbolFactory;
@@ -235,6 +253,7 @@
SymTabType m_SymTab;
size_t m_SymTabSize;
std::string m_StrTab;
+ InputBuilder& m_Builder;
};
} // namespace of mcld
diff --git a/include/mcld/LD/BranchIsland.h b/include/mcld/LD/BranchIsland.h
index 8e5cf9c..9de1380 100644
--- a/include/mcld/LD/BranchIsland.h
+++ b/include/mcld/LD/BranchIsland.h
@@ -6,22 +6,163 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef BRANCHISLAND_H
-#define BRANCHISLAND_H
+#ifndef MCLD_LD_BRANCH_ISLAND_H
+#define MCLD_LD_BRANCH_ISLAND_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
+#include <llvm/Support/DataTypes.h>
+#include <llvm/ADT/StringRef.h>
+#include <mcld/ADT/HashEntry.h>
+#include <mcld/ADT/HashTable.h>
+#include <mcld/ADT/StringHash.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Stub.h>
+#include <string>
+
namespace mcld
{
+class Stub;
+class Relocation;
+
/** \class BranchIsland
* \brief BranchIsland is a collection of stubs
*
*/
class BranchIsland
{
+public:
+ typedef SectionData::iterator iterator;
+ typedef SectionData::const_iterator const_iterator;
+ typedef std::vector<Relocation*> RelocationListType;
+ typedef RelocationListType::iterator reloc_iterator;
+ typedef RelocationListType::const_iterator const_reloc_iterator;
+
+public:
+ /*
+ * ----------
+ * --- Entry -> | Island | -> Exit ---
+ * ----------
+ */
+
+ /// BranchIsland - constructor
+ /// @param pEntryFrag - the entry fragment to the island
+ /// @param pMaxSize - the max size the island can be
+ /// @param pIndex - the inedx in the island factory
+ BranchIsland(Fragment& pEntryFrag, size_t pMaxSize, size_t pIndex);
+
+ ~BranchIsland();
+
+ /// fragment iterators of the island
+ iterator begin();
+
+ const_iterator begin() const;
+
+ iterator end();
+
+ const_iterator end() const;
+
+ /// relocation iterators of the island
+ reloc_iterator reloc_begin()
+ { return m_Relocations.begin(); }
+
+ const_reloc_iterator reloc_begin() const
+ { return m_Relocations.begin(); }
+
+ reloc_iterator reloc_end()
+ { return m_Relocations.end(); }
+
+ const_reloc_iterator reloc_end() const
+ { return m_Relocations.end(); }
+
+ /// observers
+ uint64_t offset() const;
+
+ size_t size() const;
+
+ size_t maxSize() const;
+
+ const std::string& name() const;
+
+ size_t numOfStubs() const;
+
+ /// findStub - return true if there is a stub built from the given prototype
+ /// for the given relocation
+ Stub* findStub(const Stub* pPrototype, const Relocation& pReloc);
+
+ /// addStub - add a stub into the island
+ bool addStub(const Stub* pPrototype, const Relocation& pReloc, Stub& pStub);
+
+ /// addRelocation - add a relocation into island
+ bool addRelocation(Relocation& pReloc);
+
+private:
+ /** \class Key
+ * \brief Key to recognize a stub in the island.
+ *
+ */
+ class Key
+ {
+ public:
+ Key(const Stub* pPrototype, const LDSymbol* pSymbol, Stub::SWord pAddend)
+ : m_pPrototype(pPrototype), m_pSymbol(pSymbol), m_Addend(pAddend)
+ { }
+
+ ~Key()
+ { }
+
+ const Stub* prototype() const { return m_pPrototype; }
+
+ const LDSymbol* symbol() const { return m_pSymbol; }
+
+ Stub::SWord addend() const { return m_Addend; }
+
+ struct Hash
+ {
+ size_t operator() (const Key& KEY) const
+ {
+ llvm::StringRef sym_name(KEY.symbol()->name());
+ StringHash<ELF> str_hasher;
+ return (size_t((uintptr_t)KEY.prototype())) ^
+ str_hasher(sym_name) ^
+ KEY.addend();
+ }
+ };
+
+ struct Compare
+ {
+ bool operator() (const Key& KEY1, const Key& KEY2) const
+ {
+ return (KEY1.prototype() == KEY2.prototype()) &&
+ (KEY1.symbol() == KEY2.symbol()) &&
+ (KEY1.addend() == KEY2.addend());
+ }
+ };
+
+ private:
+ const Stub* m_pPrototype;
+ const LDSymbol* m_pSymbol;
+ Stub::SWord m_Addend;
+ };
+
+ typedef HashEntry<Key, Stub*, Key::Compare> StubEntryType;
+
+ typedef HashTable<StubEntryType,
+ Key::Hash,
+ EntryFactory<StubEntryType> > StubMapType;
+private:
+ Fragment& m_Entry; // entry fragment of the island
+ Fragment* m_pExit; // exit fragment of the island
+ Fragment* m_pRear; // rear fragment of the island
+ size_t m_MaxSize;
+ std::string m_Name;
+ StubMapType m_StubMap;
+ /// m_Relocations - list of relocations created for stubs in this island
+ RelocationListType m_Relocations;
};
} // namespace of mcld
diff --git a/include/mcld/LD/BranchIslandFactory.h b/include/mcld/LD/BranchIslandFactory.h
new file mode 100644
index 0000000..755cc31
--- /dev/null
+++ b/include/mcld/LD/BranchIslandFactory.h
@@ -0,0 +1,56 @@
+//===- BranchIslandFactory.h ----------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_LD_BRANCH_ISLAND_FACTORY_H
+#define MCLD_LD_BRANCH_ISLAND_FACTORY_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/Support/GCFactory.h>
+#include <mcld/LD/BranchIsland.h>
+
+namespace mcld
+{
+
+class Fragment;
+
+/** \class BranchIslandFactory
+ * \brief
+ *
+ */
+class BranchIslandFactory : public GCFactory<BranchIsland, 0>
+{
+public:
+ /// ctor
+ /// @param pMaxBranchRange - the max branch range of the target backend
+ /// @param pMaxIslandSize - a predifned value (64KB here) to decide the max
+ /// size of the island
+ BranchIslandFactory(uint64_t pMaxBranchRange,
+ uint64_t pMaxIslandSize = 65536U);
+
+ ~BranchIslandFactory();
+
+ /// produce - produce a island for the given fragment
+ /// @param pFragment - the fragment needs a branch island
+ BranchIsland* produce(Fragment& pFragment);
+
+ /// find - find a island for the given fragment
+ /// @param pFragment - the fragment needs a branch isladn
+ BranchIsland* find(const Fragment& pFragment);
+
+private:
+ uint64_t m_MaxBranchRange;
+ uint64_t m_MaxIslandSize;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/CIE.h b/include/mcld/LD/CIE.h
deleted file mode 100644
index 23dfa22..0000000
--- a/include/mcld/LD/CIE.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- CIE.h --------------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_COMMON_INFORMATION_ENTRY_H
-#define MCLD_COMMON_INFORMATION_ENTRY_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <llvm/Support/DataTypes.h>
-#include <mcld/LD/RegionFragment.h>
-
-namespace mcld
-{
-
-/** \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
-{
-public:
- explicit CIE(MemoryRegion& pRegion, uint8_t pFDEEncode);
- ~CIE();
-
- // ----- observers ----- //
- /// getFDEEncoding - get the FDE encoding from Augmentation Data if 'R'
- /// is present in Augmentaion String
- uint8_t getFDEEncode() const
- { return m_FDEEncoding; }
-
-private:
- uint8_t m_FDEEncoding;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/DiagCommonKinds.inc b/include/mcld/LD/DiagCommonKinds.inc
index 835e1d4..08850e7 100644
--- a/include/mcld/LD/DiagCommonKinds.inc
+++ b/include/mcld/LD/DiagCommonKinds.inc
@@ -41,3 +41,8 @@
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_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.")
+DIAG(fatal_illegal_codegen_type, DiagnosticEngine::Fatal, "illegal output format of output %0", "illegal output format of output %0")
diff --git a/include/mcld/LD/DiagLayouts.inc b/include/mcld/LD/DiagLayouts.inc
index af6bc96..fac7a32 100644
--- a/include/mcld/LD/DiagLayouts.inc
+++ b/include/mcld/LD/DiagLayouts.inc
@@ -1,3 +1,6 @@
DIAG(warn_unsupported_exception, DiagnosticEngine::Warning, "Exception handling has not been fully supported yet.\nsection `%0'.", "Exception handling has not been fully supported yet.\nsection `%0'.")
DIAG(warn_unsupported_symbolic_versioning, DiagnosticEngine::Warning, "Symbolic versioning has not been fully supported yet.\nsection `%0'.", "Symbolic versioning has not been fully supported yet.\nsection `%0'")
DIAG(err_section_not_laid_out, DiagnosticEngine::Unreachable, "section %0 has not been laid out. Developers may use an output LDSection in Layout::getFragmentRef", "section %0 has not been laid out. Developers may use an output LDSection in Layout::getFragmentRef")
+DIAG(warn_duplicate_std_sectmap, DiagnosticEngine::Warning, "Duplicated definition of section map \"from %0 to %0\".", "Duplicated definition of section map \"from %0 to %0\".")
+DIAG(warn_rules_check_failed, DiagnosticEngine::Warning, "Illegal section mapping rule: %0 -> %1. (conflict with %2 -> %3)", "Illegal section mapping rule: %0 -> %1. (conflict with %2 -> %3)")
+DIAG(err_cannot_merge_section, DiagnosticEngine::Error, "Cannot merge section %0 of %1", "Cannot merge section %0 of %1")
diff --git a/include/mcld/LD/DiagReaders.inc b/include/mcld/LD/DiagReaders.inc
index 8ba28c2..3f08a21 100644
--- a/include/mcld/LD/DiagReaders.inc
+++ b/include/mcld/LD/DiagReaders.inc
@@ -1 +1,4 @@
DIAG(archive_magic_mismatch, DiagnosticEngine::Error, "magic number is mismatched in `%0'", "magic number is mismatched in `%0'")
+DIAG(debug_cannot_parse_eh, DiagnosticEngine::Debug, "cannot parse .eh_frame section in input %0", "cannot parse .eh_frame section in input %0.")
+DIAG(debug_cannot_scan_eh, DiagnosticEngine::Debug, "cannot scan .eh_frame section in input %0", "cannot scan .eh_frame section in input %0.")
+DIAG(fatal_cannot_read_input, DiagnosticEngine::Fatal, "cannot read input input %0", "cannot read input %0")
diff --git a/include/mcld/LD/DiagRelocations.inc b/include/mcld/LD/DiagRelocations.inc
index e115fd8..5d52dd8 100644
--- a/include/mcld/LD/DiagRelocations.inc
+++ b/include/mcld/LD/DiagRelocations.inc
@@ -1,9 +1,11 @@
DIAG(undefined_reference, DiagnosticEngine::Fatal, "undefined reference to `%0'", "In %1:%2, variable %0 must be defined")
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, "enexpected relocation type `%0' in object file", "unexpected relocation type `%0' in object file")
+DIAG(dynamic_relocation, DiagnosticEngine::Fatal, "unexpected relocation type `%0' in object file", "unexpected relocation type `%0' in object file")
DIAG(unsupported_relocation, DiagnosticEngine::Unreachable, "encounter unsupported relocation type `%0'\nPlease report to %1", "encounter unsupported relocation type `%0'\nPlease report to %1")
DIAG(unknown_relocation, DiagnosticEngine::Fatal, "encounter unknown relocation type `%0' for symbol `%1'", "encounter unknown relocation type `%0' for symbol `%1'")
DIAG(invalid_global_relocation, DiagnosticEngine::Unreachable, "relocation type `%0' is invalid for global symbol `%1'", "relocation type `%0' is invalid for global symbol `%1'")
DIAG(result_overflow, DiagnosticEngine::Error, "applying relocation `%0' causes overflow on symbol `%1'","applying relocation `%0' causes overflow on symbol `%1'")
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'")
diff --git a/include/mcld/LD/DiagnosticEngine.h b/include/mcld/LD/DiagnosticEngine.h
index 77666ab..9d24c7a 100644
--- a/include/mcld/LD/DiagnosticEngine.h
+++ b/include/mcld/LD/DiagnosticEngine.h
@@ -18,7 +18,7 @@
namespace mcld {
class Input;
-class MCLDInfo;
+class LinkerConfig;
class MsgHandler;
class DiagnosticPrinter;
class DiagnosticLineInfo;
@@ -61,17 +61,15 @@
~DiagnosticEngine();
- void reset(const MCLDInfo& pLDInfo);
+ void reset(const LinkerConfig& pConfig);
void setLineInfo(DiagnosticLineInfo& pLineInfo);
void setPrinter(DiagnosticPrinter& pPrinter, bool pShouldOwnPrinter = true);
- DiagnosticPrinter* getPrinter()
- { return m_pPrinter; }
+ const DiagnosticPrinter* getPrinter() const { return m_pPrinter; }
+ DiagnosticPrinter* getPrinter() { return m_pPrinter; }
- const DiagnosticPrinter* getPrinter() const
- { return m_pPrinter; }
DiagnosticPrinter* takePrinter() {
m_OwnPrinter = false;
@@ -95,7 +93,7 @@
enum {
/// MaxArguments - The maximum number of arguments we can hold. We currently
/// only support up to 10 arguments (%0-%9).
- MaxArguments = 10,
+ MaxArguments = 10
};
struct State
@@ -139,7 +137,7 @@
}
private:
- const MCLDInfo* m_pLDInfo;
+ const LinkerConfig* m_pConfig;
DiagnosticLineInfo* m_pLineInfo;
DiagnosticPrinter* m_pPrinter;
DiagnosticInfos* m_pInfoMap;
diff --git a/include/mcld/LD/DiagnosticInfos.h b/include/mcld/LD/DiagnosticInfos.h
index 66f7fc0..cb9bdbd 100644
--- a/include/mcld/LD/DiagnosticInfos.h
+++ b/include/mcld/LD/DiagnosticInfos.h
@@ -29,7 +29,7 @@
};
} // namespace of diag
-class MCLDInfo;
+class LinkerConfig;
class DiagnosticEngine;
/** \class DiagnosticInfos
@@ -38,7 +38,7 @@
class DiagnosticInfos
{
public:
- DiagnosticInfos(const MCLDInfo& pLDInfo);
+ DiagnosticInfos(const LinkerConfig& pConfig);
~DiagnosticInfos();
@@ -47,7 +47,7 @@
bool process(DiagnosticEngine& pEngine) const;
private:
- const MCLDInfo& m_LDInfo;
+ const LinkerConfig& m_Config;
};
} // namespace of mcld
diff --git a/include/mcld/LD/DiagnosticPrinter.h b/include/mcld/LD/DiagnosticPrinter.h
index 13911f5..b3617a7 100644
--- a/include/mcld/LD/DiagnosticPrinter.h
+++ b/include/mcld/LD/DiagnosticPrinter.h
@@ -28,7 +28,7 @@
virtual ~DiagnosticPrinter();
- virtual void beginInput(const Input& pInput, const MCLDInfo& pLDInfo) {}
+ virtual void beginInput(const Input& pInput, const LinkerConfig& pConfig) {}
virtual void endInput() {}
@@ -42,11 +42,8 @@
virtual void handleDiagnostic(DiagnosticEngine::Severity pSeverity,
const Diagnostic& pInfo);
- unsigned int getNumErrors() const
- { return m_NumErrors; }
-
- unsigned int getNumWarnings() const
- { return m_NumWarnings; }
+ unsigned int getNumErrors() const { return m_NumErrors; }
+ unsigned int getNumWarnings() const { return m_NumWarnings; }
protected:
unsigned int m_NumErrors;
diff --git a/include/mcld/LD/DynObjReader.h b/include/mcld/LD/DynObjReader.h
index 0900109..ddc9500 100644
--- a/include/mcld/LD/DynObjReader.h
+++ b/include/mcld/LD/DynObjReader.h
@@ -14,8 +14,7 @@
#include "mcld/LD/LDReader.h"
#include <llvm/Support/system_error.h>
-namespace mcld
-{
+namespace mcld {
class TargetLDBackend;
class Input;
@@ -33,7 +32,7 @@
public:
virtual ~DynObjReader() { }
- virtual bool readDSO(Input& pFile) = 0;
+ virtual bool readHeader(Input& pFile) = 0;
virtual bool readSymbols(Input& pFile) = 0;
diff --git a/include/mcld/LD/DynObjWriter.h b/include/mcld/LD/DynObjWriter.h
index 1c77bd4..89d9765 100644
--- a/include/mcld/LD/DynObjWriter.h
+++ b/include/mcld/LD/DynObjWriter.h
@@ -11,12 +11,14 @@
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <mcld/MC/MCLDOutput.h>
#include <mcld/LD/LDWriter.h>
#include <llvm/Support/system_error.h>
-namespace mcld
-{
+namespace mcld {
+
+class Module;
+class MemoryArea;
+class TargetLDBackend;
/** \class DynObjWriter
* \brief DynObjWriter provides an common interface for different object
@@ -32,7 +34,8 @@
public:
virtual ~DynObjWriter() { }
- virtual llvm::error_code writeDynObj(Output& pOutput) = 0;
+ virtual llvm::error_code writeDynObj(Module& pModule,
+ MemoryArea& pOutput) = 0;
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFDynObjFileFormat.h b/include/mcld/LD/ELFDynObjFileFormat.h
index 9b77e91..2ee97a6 100644
--- a/include/mcld/LD/ELFDynObjFileFormat.h
+++ b/include/mcld/LD/ELFDynObjFileFormat.h
@@ -13,23 +13,18 @@
#endif
#include <mcld/LD/ELFFileFormat.h>
-namespace mcld
-{
+namespace mcld {
-class GNULDBackend;
-class MCLinker;
+class ObjectBuilder;
/** \class ELFDynObjFileFormat
* \brief ELFDynObjFileFormat describes the format for ELF dynamic objects.
*/
class ELFDynObjFileFormat : public ELFFileFormat
{
-public:
- ELFDynObjFileFormat(GNULDBackend& pBackend) : ELFFileFormat(pBackend)
- {}
-
- void initObjectType(MCLinker& pLinker);
-
+ /// initObjectFormat - initialize sections that are dependent on shared
+ /// objects.
+ void initObjectFormat(ObjectBuilder& pBuilder, unsigned int pBitClass);
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFDynObjReader.h b/include/mcld/LD/ELFDynObjReader.h
index 72a3336..b5d59a3 100644
--- a/include/mcld/LD/ELFDynObjReader.h
+++ b/include/mcld/LD/ELFDynObjReader.h
@@ -18,7 +18,7 @@
{
class Input;
-class MCLinker;
+class FragmentLinker;
class GNULDBackend;
class ELFReaderIF;
@@ -29,20 +29,20 @@
class ELFDynObjReader : public DynObjReader
{
public:
- ELFDynObjReader(GNULDBackend& pBackend, MCLinker& pLinker);
+ ELFDynObjReader(GNULDBackend& pBackend, FragmentLinker& pLinker);
~ELFDynObjReader();
// ----- observers ----- //
bool isMyFormat(Input &pFile) const;
// ----- readers ----- //
- bool readDSO(Input& pFile);
+ bool readHeader(Input& pFile);
bool readSymbols(Input& pInput);
private:
ELFReaderIF *m_pELFReader;
- MCLinker& m_Linker;
+ FragmentLinker& m_Linker;
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFDynObjWriter.h b/include/mcld/LD/ELFDynObjWriter.h
index dc0e37b..b5dd390 100644
--- a/include/mcld/LD/ELFDynObjWriter.h
+++ b/include/mcld/LD/ELFDynObjWriter.h
@@ -11,22 +11,15 @@
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <llvm/ADT/DenseMap.h>
-#include <llvm/Support/ELF.h>
#include <mcld/LD/DynObjWriter.h>
#include <mcld/LD/ELFWriter.h>
-#include <mcld/LD/LDContext.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/Support/MemoryArea.h>
-#include <vector>
-#include <utility>
+namespace mcld {
-namespace mcld
-{
-
+class Module;
+class MemoryArea;
class GNULDBackend;
-class MCLinker;
+class FragmentLinker;
/** \class ELFDynObjWriter
* \brief ELFDynObjWriter writes the dynamic sections.
@@ -37,14 +30,13 @@
typedef ELFWriter::FileOffset FileOffset;
public:
- ELFDynObjWriter(GNULDBackend& pBackend, MCLinker& pLinker);
+ ELFDynObjWriter(GNULDBackend& pBackend, FragmentLinker& pLinker);
~ELFDynObjWriter();
- llvm::error_code writeDynObj(Output& pOutput);
+ llvm::error_code writeDynObj(Module& pModule, MemoryArea& pOutput);
private:
- GNULDBackend& m_Backend;
- MCLinker& m_Linker;
+ FragmentLinker& m_Linker;
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFExecFileFormat.h b/include/mcld/LD/ELFExecFileFormat.h
index 3c0d8bd..d888c93 100644
--- a/include/mcld/LD/ELFExecFileFormat.h
+++ b/include/mcld/LD/ELFExecFileFormat.h
@@ -13,22 +13,18 @@
#endif
#include <mcld/LD/ELFFileFormat.h>
-namespace mcld
-{
+namespace mcld {
-class GNULDBackend;
-class MCLinker;
+class ObjectBuilder;
/** \class ELFExecFileFormat
* \brief ELFExecFileFormat describes the format for ELF dynamic objects.
*/
class ELFExecFileFormat : public ELFFileFormat
{
-public:
- ELFExecFileFormat(GNULDBackend& pBackend) : ELFFileFormat(pBackend)
- {}
-
- void initObjectType(MCLinker& pLinker);
+ /// initObjectFormat - initialize sections that are dependent on executable
+ /// objects.
+ void initObjectFormat(ObjectBuilder& pBuilder, unsigned int pBitClass);
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFExecWriter.h b/include/mcld/LD/ELFExecWriter.h
index 09709f7..dc731b9 100644
--- a/include/mcld/LD/ELFExecWriter.h
+++ b/include/mcld/LD/ELFExecWriter.h
@@ -11,22 +11,15 @@
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <llvm/ADT/DenseMap.h>
-#include <llvm/Support/ELF.h>
#include <mcld/LD/ExecWriter.h>
#include <mcld/LD/ELFWriter.h>
-#include <mcld/LD/LDContext.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/Support/MemoryArea.h>
-#include <vector>
-#include <utility>
+namespace mcld {
-namespace mcld
-{
-
+class Module;
+class MemoryArea;
class GNULDBackend;
-class MCLinker;
+class FragmentLinker;
/** \class ELFDynObjWriter
* \brief ELFDynObjWriter writes the dynamic sections.
@@ -37,14 +30,13 @@
typedef ELFWriter::FileOffset FileOffset;
public:
- ELFExecWriter(GNULDBackend& pBackend, MCLinker& pLinker);
+ ELFExecWriter(GNULDBackend& pBackend, FragmentLinker& pLinker);
~ELFExecWriter();
- llvm::error_code writeExecutable(Output& pOutput);
+ llvm::error_code writeExecutable(Module& pModule, MemoryArea& pOutput);
private:
- GNULDBackend& m_Backend;
- MCLinker& m_Linker;
+ FragmentLinker& m_Linker;
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFFileFormat.h b/include/mcld/LD/ELFFileFormat.h
index f7a0c68..e52a813 100644
--- a/include/mcld/LD/ELFFileFormat.h
+++ b/include/mcld/LD/ELFFileFormat.h
@@ -14,11 +14,9 @@
#include <mcld/LD/LDFileFormat.h>
#include <mcld/LD/LDSection.h>
-namespace mcld
-{
+namespace mcld {
-class GNULDBackend;
-class MCLinker;
+class ObjectBuilder;
/** \class ELFFileFormat
* \brief ELFFileFormat describes the common file formats in ELF.
@@ -32,14 +30,16 @@
*/
class ELFFileFormat : public LDFileFormat
{
+private:
+ /// initObjectFormat - initialize sections that are dependent on object
+ /// formats. (executable, shared objects or relocatable objects).
+ virtual void
+ initObjectFormat(ObjectBuilder& pBuilder, unsigned int pBitClass) = 0;
+
public:
- ELFFileFormat(GNULDBackend& pBackend);
+ ELFFileFormat();
- virtual ~ELFFileFormat();
-
- virtual void initObjectFormat(MCLinker& pLinker);
-
- virtual void initObjectType(MCLinker& pLinker) = 0;
+ void initStdSections(ObjectBuilder& pBuilder, unsigned int pBitClass);
// ----- capacity ----- //
/// @ref Special Sections, Ch. 4.17, System V ABI, 4th edition.
@@ -174,6 +174,12 @@
bool hasStack() const
{ return (NULL != f_pStack) && (0 != f_pStack->size()); }
+ bool hasStackNote() const
+ { return (NULL != f_pStackNote); }
+
+ bool hasDataRelRoLocal() const
+ { return (NULL != f_pDataRelRoLocal) && (0 != f_pDataRelRoLocal->size()); }
+
// ----- access functions ----- //
/// @ref Special Sections, Ch. 4.17, System V ABI, 4th edition.
LDSection& getNULLSection() {
@@ -607,9 +613,28 @@
assert(NULL != f_pStack);
return *f_pStack;
}
-protected:
- GNULDBackend& f_Backend;
+ LDSection& getStackNote() {
+ assert(NULL != f_pStackNote);
+ return *f_pStackNote;
+ }
+
+ const LDSection& getStackNote() const {
+ assert(NULL != f_pStackNote);
+ return *f_pStackNote;
+ }
+
+ LDSection& getDataRelRoLocal() {
+ assert(NULL != f_pDataRelRoLocal);
+ return *f_pDataRelRoLocal;
+ }
+
+ const LDSection& getDataRelRoLocal() const {
+ assert(NULL != f_pDataRelRoLocal);
+ return *f_pDataRelRoLocal;
+ }
+
+protected:
// variable name : ELF
/// @ref Special Sections, Ch. 4.17, System V ABI, 4th edition.
LDSection* f_pNULLSection;
@@ -661,6 +686,8 @@
/// practical
LDSection* f_pStack; // .stack
+ LDSection* f_pStackNote; // .note.GNU-stack
+ LDSection* f_pDataRelRoLocal; // .data.rel.ro.local
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFObjectFileFormat.h b/include/mcld/LD/ELFObjectFileFormat.h
new file mode 100644
index 0000000..e2430db
--- /dev/null
+++ b/include/mcld/LD/ELFObjectFileFormat.h
@@ -0,0 +1,34 @@
+//===- ELFObjectFileFormat.h ----------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ELF_OBJECT_FILE_FROMAT_H
+#define MCLD_ELF_OBJECT_FILE_FROMAT_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/LD/ELFFileFormat.h>
+
+namespace mcld {
+
+class ObjectBuilder;
+
+/** \class ELFObjectFileFormat
+ * \brief ELFObjectFileFormat describes the format for ELF dynamic objects.
+ */
+class ELFObjectFileFormat : public ELFFileFormat
+{
+ void initObjectFormat(ObjectBuilder& pBuilder, unsigned int pBitClass) {
+ // do nothing
+ return;
+ }
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/ELFObjectReader.h b/include/mcld/LD/ELFObjectReader.h
index ac11261..c1463fa 100644
--- a/include/mcld/LD/ELFObjectReader.h
+++ b/include/mcld/LD/ELFObjectReader.h
@@ -13,15 +13,16 @@
#endif
#include <mcld/LD/ObjectReader.h>
-#include <llvm/Support/system_error.h>
+#include <mcld/ADT/Flags.h>
-namespace mcld
-{
+namespace mcld {
+class Module;
class Input;
-class MCLinker;
+class FragmentLinker;
class GNULDBackend;
class ELFReaderIF;
+class EhFrameReader;
/** \lclass ELFObjectReader
* \brief ELFObjectReader reads target-independent parts of ELF object file
@@ -29,7 +30,15 @@
class ELFObjectReader : public ObjectReader
{
public:
- ELFObjectReader(GNULDBackend& pBackend, MCLinker& pLinker);
+ enum ReadFlagType {
+ ParseEhFrame = 0x1, ///< parse .eh_frame section if the bit is set.
+ NumOfReadFlags = 1
+ };
+
+ typedef Flags<ReadFlagType> ReadFlag;
+
+public:
+ ELFObjectReader(GNULDBackend& pBackend, FragmentLinker& pLinker);
~ELFObjectReader();
@@ -37,7 +46,7 @@
bool isMyFormat(Input &pFile) const;
// ----- readers ----- //
- bool readObject(Input& pFile);
+ bool readHeader(Input& pFile);
virtual bool readSections(Input& pFile);
@@ -50,7 +59,10 @@
private:
ELFReaderIF* m_pELFReader;
- MCLinker& m_Linker;
+ EhFrameReader* m_pEhFrameReader;
+ FragmentLinker& m_Linker;
+ ReadFlag m_ReadFlag;
+ GNULDBackend& m_Backend;
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFObjectWriter.h b/include/mcld/LD/ELFObjectWriter.h
index a6b9a87..31f7b12 100644
--- a/include/mcld/LD/ELFObjectWriter.h
+++ b/include/mcld/LD/ELFObjectWriter.h
@@ -15,11 +15,11 @@
#include <mcld/LD/ObjectWriter.h>
#include <mcld/LD/ELFWriter.h>
-namespace mcld
-{
+namespace mcld {
-class Input;
-class MCLinker;
+class Module;
+class MemoryArea;
+class FragmentLinker;
class GNULDBackend;
/** \class ELFObjectWriter
@@ -30,15 +30,14 @@
class ELFObjectWriter : public ObjectWriter, protected ELFWriter
{
public:
- ELFObjectWriter(GNULDBackend& pBackend, MCLinker& pLinker);
+ ELFObjectWriter(GNULDBackend& pBackend, FragmentLinker& pLinker);
~ELFObjectWriter();
- llvm::error_code writeObject(Output& pOutput)
- { return llvm::make_error_code(llvm::errc::not_supported); }
+ llvm::error_code writeObject(Module& pModule, MemoryArea& pOutput);
private:
- MCLinker& m_Linker;
+ FragmentLinker& m_Linker;
};
} // namespace of mcld
diff --git a/include/mcld/LD/ELFReader.h b/include/mcld/LD/ELFReader.h
index f893be5..941c8cd 100644
--- a/include/mcld/LD/ELFReader.h
+++ b/include/mcld/LD/ELFReader.h
@@ -16,21 +16,23 @@
#include <llvm/Support/ELF.h>
#include <llvm/Support/Host.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/LD/Fragment.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/AlignFragment.h>
-#include <mcld/LD/RegionFragment.h>
#include <mcld/LD/ResolveInfo.h>
#include <mcld/LD/LDContext.h>
#include <mcld/Target/GNULDBackend.h>
#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MemoryArea.h>
#include <mcld/Support/MsgHandling.h>
-namespace mcld
-{
+namespace mcld {
+
+class Module;
+class FragmentRef;
+class FragmentLinker;
+class SectionData;
+class LDSection;
/** \class ELFReaderIF
* \brief ELFReaderIF provides common interface for all kind of ELF readers.
@@ -57,60 +59,43 @@
virtual bool isMyMachine(void* pELFHeader) const = 0;
/// fileType - the file type of this file
- virtual MCLDFile::Type fileType(void* pELFHeader) const = 0;
+ virtual Input::Type fileType(void* pELFHeader) const = 0;
/// target - the target backend
- GNULDBackend& target()
- { return m_Backend; }
+ const GNULDBackend& target() const { return m_Backend; }
+ GNULDBackend& target() { return m_Backend; }
- /// target - the target backend
- const GNULDBackend& target() const
- { return m_Backend; }
/// readSectionHeaders - read ELF section header table and create LDSections
- virtual bool readSectionHeaders(Input& pInput,
- MCLinker& pLinker,
- void* pELFHeader) const = 0;
+ virtual bool readSectionHeaders(Input& pInput, void* pELFHeader) const = 0;
/// readRegularSection - read a regular section and create fragments.
- virtual bool readRegularSection(Input& pInput,
- MCLinker& pLinker,
- LDSection& pSectHdr) const = 0;
-
- /// readRegularSection - read a target section and create fragments.
- virtual bool readTargetSection(Input& pInput,
- MCLinker& pLinker,
- LDSection& pSectHdr) = 0;
+ virtual bool readRegularSection(Input& pInput, SectionData& pSD) const = 0;
/// readSymbols - read ELF symbols and create LDSymbol
virtual bool readSymbols(Input& pInput,
- MCLinker& pLinker,
+ FragmentLinker& pLinker,
const MemoryRegion& pRegion,
const char* StrTab) const = 0;
- /// readSymbol - read a symbol from the given Input and index in symtab
+ /// readSignature - read a symbol from the given Input and index in symtab
/// This is used to get the signature of a group section.
- virtual ResolveInfo* readSymbol(Input& pInput,
- LDSection& pSymTab,
- MCLDInfo& pLDInfo,
- uint32_t pSymIdx) const = 0;
+ virtual ResolveInfo* readSignature(Input& pInput,
+ LDSection& pSymTab,
+ uint32_t pSymIdx) const = 0;
/// readRela - read ELF rela and create Relocation
virtual bool readRela(Input& pInput,
- MCLinker& pLinker,
+ FragmentLinker& pLinker,
LDSection& pSection,
const MemoryRegion& pRegion) const = 0;
/// readRel - read ELF rel and create Relocation
virtual bool readRel(Input& pInput,
- MCLinker& pLinker,
+ FragmentLinker& pLinker,
LDSection& pSection,
const MemoryRegion& pRegion) const = 0;
- bool readEhFrame(Input& pInput,
- MCLinker& pLinker,
- LDSection& pSection) const;
-
/// readDynamic - read ELF .dynamic in input dynobj
virtual bool readDynamic(Input& pInput) const = 0;
@@ -125,8 +110,6 @@
typedef std::vector<LinkInfo> LinkInfoList;
protected:
- LDFileFormat::Kind getLDSectionKind(uint32_t pType, const char* pName) const;
-
ResolveInfo::Type getSymType(uint8_t pInfo, uint16_t pShndx) const;
ResolveInfo::Desc getSymDesc(uint16_t pShndx, const Input& pInput) const;
@@ -140,13 +123,12 @@
const Input& pInput) const;
FragmentRef* getSymFragmentRef(Input& pInput,
- MCLinker& pLinker,
uint16_t pShndx,
uint32_t pOffset) const;
ResolveInfo::Visibility getSymVisibility(uint8_t pVis) const;
-private:
+protected:
GNULDBackend& m_Backend;
};
@@ -171,72 +153,60 @@
typedef llvm::ELF::Elf32_Rela Rela;
public:
- inline ELFReader(GNULDBackend& pBackend);
+ ELFReader(GNULDBackend& pBackend);
- inline ~ELFReader();
+ ~ELFReader();
/// ELFHeaderSize - return the size of the ELFHeader
- inline size_t getELFHeaderSize() const
+ size_t getELFHeaderSize() const
{ return sizeof(ELFHeader); }
/// isELF - is this a ELF file
- inline bool isELF(void* pELFHeader) const;
+ bool isELF(void* pELFHeader) const;
/// isMyEndian - is this ELF file in the same endian to me?
- inline bool isMyEndian(void* pELFHeader) const;
+ bool isMyEndian(void* pELFHeader) const;
/// isMyMachine - is this ELF file generated for the same machine.
- inline bool isMyMachine(void* pELFHeader) const;
+ bool isMyMachine(void* pELFHeader) const;
/// fileType - the file type of this file
- inline MCLDFile::Type fileType(void* pELFHeader) const;
+ Input::Type fileType(void* pELFHeader) const;
/// readSectionHeaders - read ELF section header table and create LDSections
- inline bool readSectionHeaders(Input& pInput,
- MCLinker& pLinker,
- void* pELFHeader) const;
+ bool readSectionHeaders(Input& pInput, void* pELFHeader) const;
/// readRegularSection - read a regular section and create fragments.
- inline bool readRegularSection(Input& pInput,
- MCLinker& pLinker,
- LDSection& pInputSectHdr) const;
-
- /// readRegularSection - read a target section and create fragments.
- inline bool readTargetSection(Input& pInput,
- MCLinker& pLinker,
- LDSection& pInputSectHdr);
+ bool readRegularSection(Input& pInput, SectionData& pSD) const;
/// readSymbols - read ELF symbols and create LDSymbol
- inline bool readSymbols(Input& pInput,
- MCLinker& pLinker,
+ bool readSymbols(Input& pInput,
+ FragmentLinker& pLinker,
const MemoryRegion& pRegion,
const char* StrTab) const;
- /// readSymbol - read a symbol from the given Input and index in symtab
+ /// readSignature - read a symbol from the given Input and index in symtab
/// This is used to get the signature of a group section.
- inline ResolveInfo* readSymbol(Input& pInput,
- LDSection& pSymTab,
- MCLDInfo& pLDInfo,
- uint32_t pSymIdx) const;
+ ResolveInfo* readSignature(Input& pInput,
+ LDSection& pSymTab,
+ uint32_t pSymIdx) const;
/// readRela - read ELF rela and create Relocation
- inline bool readRela(Input& pInput,
- MCLinker& pLinker,
- LDSection& pSection,
- const MemoryRegion& pRegion) const;
+ bool readRela(Input& pInput,
+ FragmentLinker& pLinker,
+ LDSection& pSection,
+ const MemoryRegion& pRegion) const;
/// readRel - read ELF rel and create Relocation
- inline bool readRel(Input& pInput,
- MCLinker& pLinker,
- LDSection& pSection,
- const MemoryRegion& pRegion) const;
+ bool readRel(Input& pInput,
+ FragmentLinker& pLinker,
+ LDSection& pSection,
+ const MemoryRegion& pRegion) const;
/// readDynamic - read ELF .dynamic in input dynobj
- inline bool readDynamic(Input& pInput) const;
+ bool readDynamic(Input& pInput) const;
};
-#include "ELFReader.tcc"
-
} // namespace of mcld
#endif
diff --git a/include/mcld/LD/ELFReader.tcc b/include/mcld/LD/ELFReader.tcc
deleted file mode 100644
index 7c3f6d4..0000000
--- a/include/mcld/LD/ELFReader.tcc
+++ /dev/null
@@ -1,596 +0,0 @@
-//===- ELFReader.tcc ------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is the template implemenation of ELFReaders
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// ELFReader<32, true>
-#include <cstring>
-#include <vector>
-
-/// constructor
-ELFReader<32, true>::ELFReader(GNULDBackend& pBackend)
- : ELFReaderIF(pBackend) {
-}
-
-/// destructor
-ELFReader<32, true>::~ELFReader()
-{
-}
-
-/// isELF - is this a ELF file
-bool ELFReader<32, true>::isELF(void* pELFHeader) const
-{
- llvm::ELF::Elf32_Ehdr* hdr =
- reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
- if (0 == memcmp(llvm::ELF::ElfMagic, hdr, 4))
- return true;
- return false;
-}
-
-/// isMyEndian - is this ELF file in the same endian to me?
-bool ELFReader<32, true>::isMyEndian(void* pELFHeader) const
-{
- llvm::ELF::Elf32_Ehdr* hdr =
- reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
-
- return (hdr->e_ident[llvm::ELF::EI_DATA] == llvm::ELF::ELFDATA2LSB);
-}
-
-/// isMyMachine - is this ELF file generated for the same machine.
-bool ELFReader<32, true>::isMyMachine(void* pELFHeader) const
-{
- llvm::ELF::Elf32_Ehdr* hdr =
- reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
-
- if (llvm::sys::isLittleEndianHost())
- return (hdr->e_machine == target().machine());
- return (bswap16(hdr->e_machine) == target().machine());
-}
-
-/// fileType - return the file type
-MCLDFile::Type ELFReader<32, true>::fileType(void* pELFHeader) const
-{
- llvm::ELF::Elf32_Ehdr* hdr =
- reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
- uint32_t type = 0x0;
- if (llvm::sys::isLittleEndianHost())
- type = hdr->e_type;
- else
- type = bswap16(hdr->e_type);
-
- switch(type) {
- case llvm::ELF::ET_REL:
- return MCLDFile::Object;
- case llvm::ELF::ET_EXEC:
- return MCLDFile::Exec;
- case llvm::ELF::ET_DYN:
- return MCLDFile::DynObj;
- case llvm::ELF::ET_CORE:
- return MCLDFile::CoreFile;
- case llvm::ELF::ET_NONE:
- default:
- return MCLDFile::Unknown;
- }
-}
-
-/// readSectionHeaders - read ELF section header table and create LDSections
-bool ELFReader<32, true>::readSectionHeaders(Input& pInput,
- MCLinker& pLinker,
- void* pELFHeader) const
-{
- llvm::ELF::Elf32_Ehdr* ehdr =
- reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
-
- uint32_t shoff = 0x0;
- uint16_t shentsize = 0x0;
- uint16_t shnum = 0x0;
- uint16_t shstrtab = 0x0;
-
- if (llvm::sys::isLittleEndianHost()) {
- shoff = ehdr->e_shoff;
- shentsize = ehdr->e_shentsize;
- shnum = ehdr->e_shnum;
- shstrtab = ehdr->e_shstrndx;
- }
- else {
- shoff = bswap32(ehdr->e_shoff);
- shentsize = bswap16(ehdr->e_shentsize);
- shnum = bswap16(ehdr->e_shnum);
- shstrtab = bswap16(ehdr->e_shstrndx);
- }
-
- // If the file has no section header table, e_shoff holds zero.
- if (0x0 == shoff)
- return true;
-
- MemoryRegion* shdr_region = pInput.memArea()->request(
- pInput.fileOffset() + shoff, shnum*shentsize);
- llvm::ELF::Elf32_Shdr* shdrTab =
- reinterpret_cast<llvm::ELF::Elf32_Shdr*>(shdr_region->start());
-
- uint32_t sh_name = 0x0;
- uint32_t sh_type = 0x0;
- uint32_t sh_flags = 0x0;
- uint32_t sh_offset = 0x0;
- uint32_t sh_size = 0x0;
- uint32_t sh_link = 0x0;
- uint32_t sh_info = 0x0;
- uint32_t sh_addralign = 0x0;
-
- // get .shstrtab first
- llvm::ELF::Elf32_Shdr* shdr = &shdrTab[shstrtab];
- if (llvm::sys::isLittleEndianHost()) {
- sh_offset = shdr->sh_offset;
- sh_size = shdr->sh_size;
- }
- else {
- sh_offset = bswap32(shdr->sh_offset);
- sh_size = bswap32(shdr->sh_size);
- }
-
- MemoryRegion* sect_name_region = pInput.memArea()->request(
- pInput.fileOffset() + sh_offset, sh_size);
- const char* sect_name =
- reinterpret_cast<const char*>(sect_name_region->start());
-
- LinkInfoList link_info_list;
-
- // create all LDSections
- for (size_t idx = 0; idx < shnum; ++idx) {
- if (llvm::sys::isLittleEndianHost()) {
- sh_name = shdrTab[idx].sh_name;
- sh_type = shdrTab[idx].sh_type;
- sh_flags = shdrTab[idx].sh_flags;
- sh_offset = shdrTab[idx].sh_offset;
- sh_size = shdrTab[idx].sh_size;
- sh_link = shdrTab[idx].sh_link;
- sh_info = shdrTab[idx].sh_info;
- sh_addralign = shdrTab[idx].sh_addralign;
- }
- else {
- sh_name = bswap32(shdrTab[idx].sh_name);
- sh_type = bswap32(shdrTab[idx].sh_type);
- sh_flags = bswap32(shdrTab[idx].sh_flags);
- sh_offset = bswap32(shdrTab[idx].sh_offset);
- sh_size = bswap32(shdrTab[idx].sh_size);
- sh_link = bswap32(shdrTab[idx].sh_link);
- sh_info = bswap32(shdrTab[idx].sh_info);
- sh_addralign = bswap32(shdrTab[idx].sh_addralign);
- }
-
- LDFileFormat::Kind kind = getLDSectionKind(sh_type,
- sect_name+sh_name);
-
- LDSection& section = pLinker.createSectHdr(sect_name+sh_name,
- kind,
- sh_type,
- sh_flags);
-
- section.setSize(sh_size);
- section.setOffset(sh_offset);
- section.setIndex(pInput.context()->numOfSections());
- section.setInfo(sh_info);
- section.setAlign(sh_addralign);
-
- if (sh_link != 0x0 || sh_info != 0x0) {
- LinkInfo link_info = { §ion, sh_link, sh_info };
- link_info_list.push_back(link_info);
- }
-
- pInput.context()->getSectionTable().push_back(§ion);
- } // end of for
-
- // set up InfoLink
- LinkInfoList::iterator info, infoEnd = link_info_list.end();
- for (info = link_info_list.begin(); info != infoEnd; ++info) {
- if (LDFileFormat::NamePool == info->section->kind() ||
- LDFileFormat::Group == info->section->kind() ||
- LDFileFormat::Note == info->section->kind()) {
- info->section->setLink(pInput.context()->getSection(info->sh_link));
- continue;
- }
- if (LDFileFormat::Relocation == info->section->kind()) {
- info->section->setLink(pInput.context()->getSection(info->sh_info));
- continue;
- }
- }
-
- pInput.memArea()->release(shdr_region);
- pInput.memArea()->release(sect_name_region);
-
- return true;
-}
-
-/// readRegularSection - read a regular section and create fragments.
-bool ELFReader<32, true>::readRegularSection(Input& pInput,
- MCLinker& pLinker,
- LDSection& pInputSectHdr) const
-{
- LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(),
- pInputSectHdr.kind(),
- pInputSectHdr.type(),
- pInputSectHdr.flag());
-
- MemoryRegion* region = pInput.memArea()->request(
- pInput.fileOffset() + pInputSectHdr.offset(), pInputSectHdr.size());
-
- SectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);
-
- Fragment* frag = NULL;
- if (NULL == region) {
- // If the input section's size is zero, we got a NULL region.
- // use a virtual fill fragment
- frag = new FillFragment(0x0, 0, 0);
- }
- else
- frag = new RegionFragment(*region);
-
- uint64_t size = pLinker.getLayout().appendFragment(*frag,
- sect_data,
- pInputSectHdr.align());
-
- out_sect.setSize(out_sect.size() + size);
- return true;
-}
-
-/// readRegularSection - read a target section and create fragments.
-bool ELFReader<32, true>::readTargetSection(Input& pInput,
- MCLinker& pLinker,
- LDSection& pInputSectHdr)
-{
- return target().readSection(pInput, pLinker, pInputSectHdr);
-}
-
-/// readSymbols - read ELF symbols and create LDSymbol
-bool ELFReader<32, true>::readSymbols(Input& pInput,
- MCLinker& pLinker,
- const MemoryRegion& pRegion,
- const char* pStrTab) const
-{
- // get number of symbols
- size_t entsize = pRegion.size()/sizeof(llvm::ELF::Elf32_Sym);
- const llvm::ELF::Elf32_Sym* symtab =
- reinterpret_cast<const llvm::ELF::Elf32_Sym*>(pRegion.start());
-
- uint32_t st_name = 0x0;
- uint32_t st_value = 0x0;
- uint32_t st_size = 0x0;
- uint8_t st_info = 0x0;
- uint8_t st_other = 0x0;
- uint16_t st_shndx = 0x0;
- // skip the first NULL symbol
- pInput.context()->addSymbol(NULL);
-
- for (size_t idx = 1; idx < entsize; ++idx) {
- st_info = symtab[idx].st_info;
- st_other = symtab[idx].st_other;
-
- if (llvm::sys::isLittleEndianHost()) {
- st_name = symtab[idx].st_name;
- st_value = symtab[idx].st_value;
- st_size = symtab[idx].st_size;
- st_shndx = symtab[idx].st_shndx;
- }
- else {
- st_name = bswap32(symtab[idx].st_name);
- st_value = bswap32(symtab[idx].st_value);
- st_size = bswap32(symtab[idx].st_size);
- st_shndx = bswap16(symtab[idx].st_shndx);
- }
-
- // If the section should not be included, set the st_shndx SHN_UNDEF
- // - A section in interrelated groups are not included.
- if (pInput.type() == Input::Object &&
- st_shndx < llvm::ELF::SHN_LORESERVE &&
- st_shndx != llvm::ELF::SHN_UNDEF) {
- if (NULL == pInput.context()->getSection(st_shndx))
- st_shndx = llvm::ELF::SHN_UNDEF;
- }
-
- // get ld_type
- ResolveInfo::Type ld_type = getSymType(st_info, st_shndx);
-
- // get ld_desc
- ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
-
- // get ld_binding
- ResolveInfo::Binding ld_binding = getSymBinding((st_info >> 4), st_shndx, st_other);
-
- // get ld_value - ld_value must be section relative.
- uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
-
- // get the input fragment
- FragmentRef* ld_frag_ref = getSymFragmentRef(pInput,
- pLinker,
- st_shndx,
- ld_value);
-
- // get ld_vis
- ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
-
- // get ld_name
- llvm::StringRef ld_name;
- if (ResolveInfo::Section == ld_type) {
- // Section symbol's st_name is the section index.
- LDSection* section = pInput.context()->getSection(st_shndx);
- assert(NULL != section && "get a invalid section");
- ld_name = llvm::StringRef(section->name());
- }
- else {
- ld_name = llvm::StringRef(pStrTab + st_name);
- }
-
-
- // push into MCLinker
- LDSymbol* input_sym = NULL;
-
- if (pInput.type() == Input::Object) {
- input_sym = pLinker.addSymbol<Input::Object>(ld_name,
- ld_type,
- ld_desc,
- ld_binding,
- st_size,
- ld_value,
- ld_frag_ref,
- ld_vis);
- // push into the input file
- pInput.context()->addSymbol(input_sym);
- continue;
- }
- else if (pInput.type() == Input::DynObj) {
- input_sym = pLinker.addSymbol<Input::DynObj>(ld_name,
- ld_type,
- ld_desc,
- ld_binding,
- st_size,
- ld_value,
- ld_frag_ref,
- ld_vis);
- continue;
- }
-
- } // end of for loop
- return true;
-}
-
-/// readSymbol - read a symbol from the given Input and index in symtab
-/// This is used to get the signature of a group section.
-ResolveInfo* ELFReader<32, true>::readSymbol(Input& pInput,
- LDSection& pSymTab,
- MCLDInfo& pLDInfo,
- uint32_t pSymIdx) const
-{
- LDSection* symtab = &pSymTab;
- LDSection* strtab = symtab->getLink();
- assert(NULL != symtab && NULL != strtab);
-
- uint32_t offset = pInput.fileOffset() + symtab->offset() +
- sizeof(llvm::ELF::Elf32_Sym) * pSymIdx;
- MemoryRegion* symbol_region =
- pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf32_Sym));
- llvm::ELF::Elf32_Sym* entry =
- reinterpret_cast<llvm::ELF::Elf32_Sym*>(symbol_region->start());
-
- uint32_t st_name = 0x0;
- uint32_t st_size = 0x0;
- uint8_t st_info = 0x0;
- uint8_t st_other = 0x0;
- uint16_t st_shndx = 0x0;
- st_info = entry->st_info;
- st_other = entry->st_other;
- if (llvm::sys::isLittleEndianHost()) {
- st_name = entry->st_name;
- st_size = entry->st_size;
- st_shndx = entry->st_shndx;
- }
- else {
- st_name = bswap32(entry->st_name);
- st_size = bswap32(entry->st_size);
- st_shndx = bswap16(entry->st_shndx);
- }
-
- MemoryRegion* strtab_region = pInput.memArea()->request(
- pInput.fileOffset() + strtab->offset(), strtab->size());
-
- // get ld_name
- llvm::StringRef ld_name(
- reinterpret_cast<char*>(strtab_region->start() + st_name));
-
- // get ld_type
- ResolveInfo::Type ld_type = static_cast<ResolveInfo::Type>(st_info & 0xF);
-
- // get ld_desc
- ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
-
- // get ld_binding
- ResolveInfo::Binding ld_binding =
- getSymBinding((st_info >> 4), st_shndx, st_other);
-
- // get ld_vis
- ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
-
- ResolveInfo* result =
- pLDInfo.getNamePool().createSymbol(ld_name,
- (pInput.type() == Input::DynObj),
- ld_type,
- ld_desc,
- ld_binding,
- st_size,
- ld_vis);
- // release regions
- pInput.memArea()->release(symbol_region);
- pInput.memArea()->release(strtab_region);
-
- return result;
-}
-
-/// readRela - read ELF rela and create Relocation
-bool ELFReader<32, true>::readRela(Input& pInput,
- MCLinker& pLinker,
- LDSection& pSection,
- const MemoryRegion& pRegion) const
-{
- // get the number of rela
- size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rela);
- const llvm::ELF::Elf32_Rela* relaTab =
- reinterpret_cast<const llvm::ELF::Elf32_Rela*>(pRegion.start());
-
- for (size_t idx=0; idx < entsize; ++idx) {
- uint32_t r_offset = 0x0;
- uint32_t r_info = 0x0;
- int32_t r_addend = 0;
- if (llvm::sys::isLittleEndianHost()) {
- r_offset = relaTab[idx].r_offset;
- r_info = relaTab[idx].r_info;
- r_addend = relaTab[idx].r_addend;
- }
- else {
- r_offset = bswap32(relaTab[idx].r_offset);
- r_info = bswap32(relaTab[idx].r_info);
- r_addend = bswap32(relaTab[idx].r_addend);
- }
-
- uint8_t r_type = static_cast<unsigned char>(r_info);
- uint32_t r_sym = (r_info >> 8);
- LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
- if (NULL == symbol)
- fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
-
- ResolveInfo* resolve_info = symbol->resolveInfo();
-
- FragmentRef* frag_ref =
- pLinker.getLayout().getFragmentRef(*pSection.getLink(), r_offset);
-
- if (NULL == frag_ref) {
- fatal(diag::err_cannot_read_relocated_section)
- << pSection.name()
- << pSection.getLink()->index()
- << pInput.path();
- }
-
- pLinker.addRelocation(r_type, *symbol, *resolve_info, *frag_ref, pSection, r_addend);
- }
- return true;
-}
-
-/// readRel - read ELF rel and create Relocation
-bool ELFReader<32, true>::readRel(Input& pInput,
- MCLinker& pLinker,
- LDSection& pSection,
- const MemoryRegion& pRegion) const
-{
- // get the number of rel
- size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rel);
- const llvm::ELF::Elf32_Rel* relTab =
- reinterpret_cast<const llvm::ELF::Elf32_Rel*>(pRegion.start());
-
- for (size_t idx=0; idx < entsize; ++idx) {
- uint32_t r_offset = 0x0;
- uint32_t r_info = 0x0;
- if (llvm::sys::isLittleEndianHost()) {
- r_offset = relTab[idx].r_offset;
- r_info = relTab[idx].r_info;
- }
- else {
- r_offset = bswap32(relTab[idx].r_offset);
- r_info = bswap32(relTab[idx].r_info);
- }
-
- uint8_t r_type = static_cast<unsigned char>(r_info);
- uint32_t r_sym = (r_info >> 8);
-
- LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
- if (NULL == symbol) {
- fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
- }
-
- ResolveInfo* resolve_info = symbol->resolveInfo();
-
- FragmentRef* frag_ref =
- pLinker.getLayout().getFragmentRef(*pSection.getLink(), r_offset);
-
- if (NULL == frag_ref) {
- fatal(diag::err_cannot_read_relocated_section)
- << pSection.name()
- << pSection.getLink()->index()
- << pInput.path();
- }
-
- pLinker.addRelocation(r_type, *symbol, *resolve_info, *frag_ref, pSection);
- }
- return true;
-}
-
-/// readDynamic - read ELF .dynamic in input dynobj
-bool ELFReader<32, true>::readDynamic(Input& pInput) const
-{
- assert(pInput.type() == Input::DynObj);
- const LDSection* dynamic_sect = pInput.context()->getSection(".dynamic");
- if (NULL == dynamic_sect) {
- fatal(diag::err_cannot_read_section) << ".dynamic";
- }
- const LDSection* dynstr_sect = dynamic_sect->getLink();
- if (NULL == dynstr_sect) {
- fatal(diag::err_cannot_read_section) << ".dynstr";
- }
-
- MemoryRegion* dynamic_region = pInput.memArea()->request(
- pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
-
- MemoryRegion* dynstr_region = pInput.memArea()->request(
- pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
-
- assert(NULL != dynamic_region && NULL != dynstr_region);
-
- const llvm::ELF::Elf32_Dyn* dynamic =
- (llvm::ELF::Elf32_Dyn*) dynamic_region->start();
- const char* dynstr = (const char*) dynstr_region->start();
- bool hasSOName = false;
- size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf32_Dyn);
-
- for (size_t idx = 0; idx < numOfEntries; ++idx) {
-
- llvm::ELF::Elf32_Sword d_tag = 0x0;
- llvm::ELF::Elf32_Word d_val = 0x0;
-
- if (llvm::sys::isLittleEndianHost()) {
- d_tag = dynamic[idx].d_tag;
- d_val = dynamic[idx].d_un.d_val;
- } else {
- d_tag = bswap32(dynamic[idx].d_tag);
- d_val = bswap32(dynamic[idx].d_un.d_val);
- }
-
- switch (d_tag) {
- case llvm::ELF::DT_SONAME:
- assert(d_val < dynstr_sect->size());
- pInput.setSOName(dynstr + d_val);
- hasSOName = true;
- break;
- case llvm::ELF::DT_NEEDED:
- // TODO:
- break;
- case llvm::ELF::DT_NULL:
- default:
- break;
- }
- }
-
- // if there is no SONAME in .dynamic, then set it from input path
- if (!hasSOName)
- pInput.setSOName(pInput.path().native());
-
- pInput.memArea()->release(dynamic_region);
- pInput.memArea()->release(dynstr_region);
- return true;
-}
-
diff --git a/include/mcld/LD/ELFSectionMap.h b/include/mcld/LD/ELFSectionMap.h
deleted file mode 100644
index e832fa9..0000000
--- a/include/mcld/LD/ELFSectionMap.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//===- ELFSectionMap.h ----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_ELF_SECTION_MAP_H
-#define MCLD_LD_ELF_SECTION_MAP_H
-
-#include <mcld/LD/SectionMap.h>
-
-namespace mcld
-{
-
-class ELFSectionMap : public SectionMap
-{
-public:
- ELFSectionMap();
-
- ~ELFSectionMap();
-
- void initStandardMaps();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/ELFSegment.h b/include/mcld/LD/ELFSegment.h
index 8b9ff98..d7f769e 100644
--- a/include/mcld/LD/ELFSegment.h
+++ b/include/mcld/LD/ELFSegment.h
@@ -41,45 +41,15 @@
~ELFSegment();
/// ----- iterators ----- ///
- sect_iterator sectBegin()
- { return m_SectionList.begin(); }
+ 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(); }
- sect_iterator sectEnd()
- { return m_SectionList.end(); }
-
- const_sect_iterator sectBegin() const
- { return m_SectionList.begin(); }
-
- const_sect_iterator sectEnd() const
- { return m_SectionList.end(); }
-
- LDSection* getFirstSection()
- {
- if (0 == numOfSections())
- return NULL;
- return m_SectionList[0];
- }
-
- LDSection* getLastSection()
- {
- if (0 == numOfSections())
- return NULL;
- return m_SectionList[numOfSections() - 1];
- }
-
- const LDSection* getFirstSection() const
- {
- if (0 == numOfSections())
- return NULL;
- return m_SectionList[0];
- }
-
- const LDSection* getLastSection() const
- {
- if (0 == numOfSections())
- return NULL;
- return m_SectionList[numOfSections() - 1];
- }
+ LDSection* front() { return m_SectionList.front(); }
+ const LDSection* front() const { return m_SectionList.front(); }
+ LDSection* back() { return m_SectionList.back(); }
+ const LDSection* back() const { return m_SectionList.back(); }
/// ----- observers ----- ///
uint32_t type() const
@@ -109,6 +79,10 @@
size_t numOfSections() const
{ return m_SectionList.size(); }
+ bool isDataSegment() const;
+
+ bool isBssSegment() const;
+
/// ----- modifiers ----- ///
void setOffset(uint64_t pOffset)
{ m_Offset = pOffset; }
diff --git a/include/mcld/LD/ELFWriter.h b/include/mcld/LD/ELFWriter.h
index 3a73605..b0c4d81 100644
--- a/include/mcld/LD/ELFWriter.h
+++ b/include/mcld/LD/ELFWriter.h
@@ -13,17 +13,20 @@
#endif
#include <llvm/Support/ELF.h>
-#include <mcld/MC/MCLDOutput.h>
-namespace mcld
-{
+namespace mcld {
-class MCLDInfo;
-class Layout;
+class Module;
+class FragmentLinker;
+class LinkerConfig;
class GNULDBackend;
class Relocation;
class LDSection;
class SectionData;
+class RelocData;
+class Output;
+class MemoryRegion;
+class MemoryArea;
/** \class ELFWriter
* \brief ELFWriter provides basic functions to write ELF sections, symbols,
@@ -48,54 +51,47 @@
const GNULDBackend& target() const
{ return f_Backend; }
- virtual void writeELF32Header(const MCLDInfo& pInfo,
- const Layout& pLayout,
- const GNULDBackend& pBackend,
- Output& pOutput) const;
+ virtual void writeELF32Header(const LinkerConfig& pConfig,
+ const Module& pModule,
+ MemoryArea& pOutput) const;
- virtual void writeELF64Header(const MCLDInfo& pInfo,
- const Layout& pLayout,
- const GNULDBackend& pBackend,
- Output& pOutput) const;
+ virtual void writeELF64Header(const LinkerConfig& pConfig,
+ const Module& pModule,
+ MemoryArea& pOutput) const;
- virtual uint64_t getEntryPoint(const MCLDInfo& pInfo,
- const Layout& pLayout,
- const GNULDBackend& pBackend,
- const Output& pOutput) const;
+ virtual uint64_t getEntryPoint(const LinkerConfig& pConfig,
+ const Module& pModule) const;
protected:
- void emitELF32SectionHeader(Output& pOutput, MCLinker& pLinker) const;
+ void emitELF32SectionHeader(const Module& pModule,
+ const LinkerConfig& pConfig,
+ MemoryArea& pOutput) const;
- void emitELF64SectionHeader(Output& pOutput, MCLinker& pLinker) const;
+ void emitELF64SectionHeader(const Module& pModule,
+ const LinkerConfig& pConfig,
+ MemoryArea& pOutput) const;
- void emitELF32ProgramHeader(Output& pOutput,
- const GNULDBackend& pBackend) const;
+ void emitELF32ProgramHeader(MemoryArea& pOutput) const;
- void emitELF64ProgramHeader(Output& pOutput,
- const GNULDBackend& pBackend) const;
+ void emitELF64ProgramHeader(MemoryArea& pOutput) const;
// emitShStrTab - emit .shstrtab
- void emitELF32ShStrTab(Output& pOutput, MCLinker& pLinker) const;
+ void emitELFShStrTab(const LDSection& pShStrTab, const Module& pModule,
+ MemoryArea& pOutput);
- void emitELF64ShStrTab(Output& pOutput, MCLinker& pLinker) const;
-
- void emitSectionData(const Layout& pLayout,
- const LDSection& pSection,
+ void emitSectionData(const LDSection& pSection,
MemoryRegion& pRegion) const;
- void emitRelocation(const Layout& pLayout,
- const Output& pOutput,
+ void emitRelocation(const LinkerConfig& pConfig,
const LDSection& pSection,
MemoryRegion& pRegion) const;
- void emitRel(const Layout& pLayout,
- const Output& pOutput,
- const SectionData& pSectionData,
+ void emitRel(const LinkerConfig& pConfig,
+ const RelocData& pRelocData,
MemoryRegion& pRegion) const;
- void emitRela(const Layout& pLayout,
- const Output& pOutput,
- const SectionData& pSectionData,
+ void emitRela(const LinkerConfig& pConfig,
+ const RelocData& pRelocData,
MemoryRegion& pRegion) const;
private:
@@ -106,14 +102,17 @@
uint64_t getELF64SectEntrySize(const LDSection& pSection) const;
// getSectEntrySize - compute ElfXX_Shdr::sh_link
- uint64_t getSectLink(const LDSection& pSection, const Output& pOutput) const;
+ uint64_t getSectLink(const LDSection& pSection,
+ const LinkerConfig& pConfig) const;
// getSectEntrySize - compute ElfXX_Shdr::sh_info
- uint64_t getSectInfo(const LDSection& pSection, const Output& pOutput) const;
+ uint64_t getSectInfo(const LDSection& pSection) const;
- uint64_t getELF32LastStartOffset(const Output& pOutput) const;
+ uint64_t getELF32LastStartOffset(const Module& pModule) const;
- uint64_t getELF64LastStartOffset(const Output& pOutput) const;
+ uint64_t getELF64LastStartOffset(const Module& pModule) const;
+
+ void emitSectionData(const SectionData& pSD, MemoryRegion& pRegion) const;
protected:
GNULDBackend& f_Backend;
diff --git a/include/mcld/LD/EhFrame.h b/include/mcld/LD/EhFrame.h
index 9497d79..dc360a2 100644
--- a/include/mcld/LD/EhFrame.h
+++ b/include/mcld/LD/EhFrame.h
@@ -6,136 +6,130 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_EXCEPTION_HANDLING_FRAME_H
-#define MCLD_EXCEPTION_HANDLING_FRAME_H
+#ifndef MCLD_LD_EH_FRAME_H
+#define MCLD_LD_EH_FRAME_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
+
#include <vector>
+#include <mcld/Fragment/RegionFragment.h>
-#include <mcld/ADT/TypeTraits.h>
-#include <mcld/LD/CIE.h>
-#include <mcld/LD/FDE.h>
-#include <mcld/LD/RegionFragment.h>
-#include <mcld/Support/GCFactory.h>
+namespace mcld {
-namespace mcld
-{
-
-class Input;
-class Layout;
+class LDSection;
class SectionData;
-class TargetLDBackend;
/** \class EhFrame
* \brief EhFrame represents .eh_frame section
- * EhFrame is responsible to parse the input eh_frame sections and create
- * the corresponding CIE and FDE entries.
*/
class EhFrame
{
public:
- typedef ConstTraits<unsigned char>::pointer ConstAddress;
- typedef std::vector<CIE*> CIEListType;
- typedef std::vector<FDE*> FDEListType;
- typedef CIEListType::iterator cie_iterator;
- typedef CIEListType::const_iterator const_cie_iterator;
- typedef FDEListType::iterator fde_iterator;
- typedef FDEListType::const_iterator const_fde_iterator;
+ /** \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
+ {
+ public:
+ CIE(MemoryRegion& pRegion);
+
+ void setFDEEncode(uint8_t pEncode) { m_FDEEncode = pEncode; }
+ uint8_t getFDEEncode() const { return m_FDEEncode; }
+
+ private:
+ uint8_t m_FDEEncode;
+ };
+
+ /** \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
+ {
+ public:
+ FDE(MemoryRegion& pRegion,
+ const CIE& pCIE,
+ uint32_t pDataStart);
+
+ const CIE& getCIE() const { return m_CIE; }
+
+ uint32_t getDataStart() const { return m_DataStart; }
+ private:
+ const CIE& m_CIE;
+ uint32_t m_DataStart;
+ };
+
+ typedef std::vector<CIE*> CIEList;
+
+ // 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;
+
+ typedef std::vector<FDE*> FDEList;
+
+ // 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;
public:
- EhFrame();
+ EhFrame(LDSection& pSection);
+
~EhFrame();
- /// readEhFrame - read an .eh_frame section and create the corresponding
- /// CIEs and FDEs
- /// @param pSD - the SectionData of this input eh_frame
- /// @param pSection - the input eh_frame
- /// @param pArea - the memory area which pSection is within.
- /// @ return - size of this eh_frame section, 0 if we do not recognize
- /// this eh_frame or this is an empty section
- uint64_t readEhFrame(Layout& pLayout,
- const TargetLDBackend& pBackend,
- SectionData& pSD,
- const Input& pInput,
- LDSection& pSection,
- MemoryArea& pArea);
+ /// merge - move all data from pOther to this object.
+ EhFrame& merge(EhFrame& pOther);
- // ----- observers ----- //
- cie_iterator cie_begin()
- { return m_CIEs.begin(); }
+ const LDSection& getSection() const { return m_Section; }
+ LDSection& getSection() { return m_Section; }
- const_cie_iterator cie_begin() const
- { return m_CIEs.begin(); }
+ const SectionData& getSectionData() const { return *m_pSectionData; }
+ SectionData& getSectionData() { return *m_pSectionData; }
- cie_iterator cie_end()
- { return m_CIEs.end(); }
+ // ----- 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);
- const_cie_iterator cie_end() const
- { return m_CIEs.end(); }
+ /// addCIE - add a CIE entry in EhFrame
+ void addCIE(CIE& pCIE);
- fde_iterator fde_begin()
- { return m_FDEs.begin(); }
+ /// addFDE - add a FDE entry in EhFrame
+ void addFDE(FDE& pFDE);
- const_fde_iterator fde_begin() const
- { return m_FDEs.begin(); }
+ // ----- CIE ----- //
+ const_cie_iterator cie_begin() const { return m_CIEs.begin(); }
+ cie_iterator cie_begin() { return m_CIEs.begin(); }
+ const_cie_iterator cie_end () const { return m_CIEs.end(); }
+ cie_iterator cie_end () { return m_CIEs.end(); }
- fde_iterator fde_end()
- { return m_FDEs.end(); }
+ const CIE& cie_front() const { return *m_CIEs.front(); }
+ CIE& cie_front() { return *m_CIEs.front(); }
+ const CIE& cie_back () const { return *m_CIEs.back(); }
+ CIE& cie_back () { return *m_CIEs.back(); }
- const_fde_iterator fde_end() const
- { return m_FDEs.end(); }
+ size_t numOfCIEs() const { return m_CIEs.size(); }
- /// getFDECount - the number of FDE entries
- size_t getFDECount()
- { return m_FDEs.size(); }
+ // ----- 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(); }
- size_t getFDECount() const
- { return m_FDEs.size(); }
+ 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(); }
- /// canRecognizeAllEhFrame - return if we are able to parse all input
- /// eh_frame sections
- /// @return false - if there is any input .eh_frame section that
- /// we are not able to recognize
- bool canRecognizeAllEhFrame()
- { return m_fCanRecognizeAll; }
-
- bool canRecognizeAllEhFrame() const
- { return m_fCanRecognizeAll; }
+ size_t numOfFDEs() const { return m_FDEs.size(); }
private:
- typedef std::vector<Fragment*> FragListType;
+ LDSection& m_Section;
+ SectionData* m_pSectionData;
-private:
- /// addCIE - parse and create a CIE entry
- /// @return false - cannot recognize this CIE
- bool addCIE(MemoryRegion& pFrag,
- const TargetLDBackend& pBackend,
- FragListType& pFragList);
-
- /// addFDE - parse and create an FDE entry
- /// @return false - cannot recognize this FDE
- bool addFDE(MemoryRegion& pFrag,
- const TargetLDBackend& pBackend,
- FragListType& pFragList);
-
- /// readVal - read a 32 bit data from pAddr, swap it if needed
- uint32_t readVal(ConstAddress pAddr, bool pIsTargetLittleEndian);
-
- /// skipLEB128 - skip the first LEB128 encoded value from *pp, update *pp
- /// to the next character.
- /// @return - false if we ran off the end of the string.
- /// @ref - GNU gold 1.11, ehframe.h, Eh_frame::skip_leb128.
- bool skipLEB128(ConstAddress* pp, ConstAddress pend);
-
- /// deleteFragments - release the MemoryRegion and delete Fragments in pList
- void deleteFragments(FragListType& pList, MemoryArea& pArea);
-
-private:
- CIEListType m_CIEs;
- FDEListType m_FDEs;
-
- bool m_fCanRecognizeAll;
+ CIEList m_CIEs;
+ FDEList m_FDEs;
};
} // namespace of mcld
diff --git a/include/mcld/LD/EhFrameHdr.h b/include/mcld/LD/EhFrameHdr.h
index 70f915c..3a5971d 100644
--- a/include/mcld/LD/EhFrameHdr.h
+++ b/include/mcld/LD/EhFrameHdr.h
@@ -11,36 +11,34 @@
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <llvm/Support/Dwarf.h>
-#include <llvm/Support/DataTypes.h>
#include <mcld/ADT/SizeTraits.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/LD/CIE.h>
-#include <mcld/LD/FDE.h>
-#include <mcld/LD/Layout.h>
+#include <cassert>
-namespace mcld
-{
-class EhFrame;
+#include <mcld/LD/EhFrame.h>
+namespace mcld {
+
class LDSection;
-class Output;
-class FDE;
-class MCLinker;
+class MemoryArea;
+class MemoryRegion;
/** \class EhFrameHdr
* \brief EhFrameHdr represents .eh_frame_hdr section.
+ *
+ * @ref lsb core generic 4.1
+ * .eh_frame_hdr section format
+ * uint8_t : version
+ * uint8_t : eh_frame_ptr_enc
+ * uint8_t : fde_count_enc
+ * uint8_t : table_enc
+ * uint32_t : eh_frame_ptr
+ * uint32_t : fde_count
+ * __________________________ when fde_count > 0
+ * <uint32_t, uint32_t>+ : binary search table
*/
class EhFrameHdr
{
public:
- EhFrameHdr(const EhFrame& pEhFrameData,
- const LDSection& pEhFrameSect,
- LDSection& pEhFrameHdrSect);
+ EhFrameHdr(LDSection& pEhFrameHdr, const LDSection& pEhFrame);
~EhFrameHdr();
@@ -49,49 +47,28 @@
/// emitOutput - write out eh_frame_hdr
template<size_t size>
- void emitOutput(Output& pOutput, MCLinker& pLinker);
+ void emitOutput(MemoryArea& pOutput)
+ { assert(false && "Call invalid EhFrameHdr::emitOutput"); }
private:
- /// getFDEPC - return the address of FDE's pc
- /// @param pFDE - FDE
- /// @param pOffset - the output offset of FDE
- template<size_t size>
- typename SizeTraits<size>::Address
- getFDEPC(const FDE& pFDE,
- typename SizeTraits<size>::Offset pOffset,
- const MemoryRegion& pEhFrameRegion);
-
- template<size_t size>
- class BSTEntry
- {
- public:
- typedef std::pair<typename SizeTraits<size>::Address,
- typename SizeTraits<size>::Address> EntryType;
- };
-
- template<size_t size>
- struct BSTEntryCompare
- : public std::binary_function<const typename BSTEntry<size>::EntryType&,
- const typename BSTEntry<size>::EntryType&,
- bool>
- {
- bool operator()(const typename BSTEntry<size>::EntryType& X,
- const typename BSTEntry<size>::EntryType& Y) const
- { return X.first < Y.first; }
- };
+ /// computePCBegin - return the address of FDE's pc
+ /// @ref binutils gold: ehframe.cc:222
+ uint32_t computePCBegin(const EhFrame::FDE& pFDE, const MemoryRegion& pEhFrameRegion);
private:
- /// eh_frame data
- const EhFrame& m_EhFrameData;
-
- /// .eh_frame section
- const LDSection& m_EhFrameSect;
-
/// .eh_frame_hdr section
- LDSection& m_EhFrameHdrSect;
+ LDSection& m_EhFrameHdr;
+
+ /// eh_frame
+ const LDSection& m_EhFrame;
};
-#include "EhFrameHdr.tcc"
+//===----------------------------------------------------------------------===//
+// Template Specification Functions
+//===----------------------------------------------------------------------===//
+/// emitOutput - write out eh_frame_hdr
+template<>
+void EhFrameHdr::emitOutput<32>(MemoryArea& pOutput);
} // namespace of mcld
diff --git a/include/mcld/LD/EhFrameHdr.tcc b/include/mcld/LD/EhFrameHdr.tcc
deleted file mode 100644
index 3b7d8ee..0000000
--- a/include/mcld/LD/EhFrameHdr.tcc
+++ /dev/null
@@ -1,163 +0,0 @@
-//===- EhFrameHdr.tcc -----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <vector>
-
-using namespace mcld;
-using namespace llvm::dwarf;
-
-/// emitOutput - write out eh_frame_hdr
-template<size_t size>
-void EhFrameHdr::emitOutput(Output& pOutput, MCLinker& pLinker)
-{
- MemoryRegion* ehframe_region =
- pOutput.memArea()->request(m_EhFrameSect.offset(), m_EhFrameSect.size());
-
- MemoryRegion* ehframehdr_region =
- pOutput.memArea()->request(m_EhFrameHdrSect.offset(),
- m_EhFrameHdrSect.size());
-
- uint8_t* data = (uint8_t*)ehframehdr_region->start();
- // version
- data[0] = 1;
- // eh_frame_ptr_enc
- data[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
-
- // eh_frame_ptr
- uint32_t* eh_frame_ptr = (uint32_t*)(data + 4);
- *eh_frame_ptr = m_EhFrameSect.addr() - (m_EhFrameHdrSect.addr() + 4);
-
- // fde_count
- uint32_t* fde_count = (uint32_t*)(data + 8);
- *fde_count = m_EhFrameData.getFDECount();
-
- if (m_EhFrameData.getFDECount() != 0 &&
- m_EhFrameData.canRecognizeAllEhFrame()) {
- // fde_count_enc
- data[2] = DW_EH_PE_udata4;
- // table_enc
- data[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
-
- // prepare the binary search table
- typedef std::vector<typename BSTEntry<size>::EntryType> SearchTableType;
- SearchTableType search_table;
- EhFrame::const_fde_iterator fde = m_EhFrameData.fde_begin(),
- fde_end = m_EhFrameData.fde_end();
- for(; fde != fde_end; ++fde) {
- assert(*fde != NULL);
- typename SizeTraits<size>::Offset offset;
- typename SizeTraits<size>::Address fde_pc;
- typename SizeTraits<size>::Address fde_addr;
- offset = pLinker.getLayout().getOutputOffset(**fde);
- fde_pc = getFDEPC<size>(**fde, offset, *ehframe_region);
- fde_addr = m_EhFrameSect.addr() + offset;
- search_table.push_back(std::make_pair(fde_pc, fde_addr));
- }
-
- std::sort(search_table.begin(), search_table.end(), BSTEntryCompare<size>());
-
- // write out the binary search table
- uint32_t* bst = (uint32_t*)(data + 12);
- typename SearchTableType::const_iterator entry = search_table.begin(),
- entry_end = search_table.end();
- for (size_t id = 0; entry != entry_end; ++entry) {
- bst[id++] = (*entry).first - m_EhFrameHdrSect.addr();
- bst[id++] = (*entry).second - m_EhFrameHdrSect.addr();
- }
- } else {
- // fde_count_enc
- data[2] = DW_EH_PE_omit;
- // table_enc
- data[3] = DW_EH_PE_omit;
- }
-
- pOutput.memArea()->release(ehframe_region);
- pOutput.memArea()->release(ehframehdr_region);
-}
-
-/// getFDEPC - return the address of FDE's pc
-/// @ref binutils gold: ehframe.cc:222
-template<size_t size>
-typename SizeTraits<size>::Address
-EhFrameHdr::getFDEPC(const FDE& pFDE,
- typename SizeTraits<size>::Offset pOffset,
- const MemoryRegion& pEhFrameRegion)
-{
- uint8_t fde_encoding = pFDE.getCIE().getFDEEncode();
- unsigned int eh_value = fde_encoding & 0x7;
-
- // check the size to read in
- if (eh_value == llvm::dwarf::DW_EH_PE_absptr) {
- if (size == 32)
- eh_value = DW_EH_PE_udata4;
- else if (size == 64)
- eh_value = DW_EH_PE_udata8;
- }
-
- size_t pc_size = 0x0;
- switch (eh_value) {
- case DW_EH_PE_udata2:
- pc_size = 2;
- break;
- case DW_EH_PE_udata4:
- pc_size = 4;
- break;
- case DW_EH_PE_udata8:
- pc_size = 8;
- break;
- default:
- // TODO
- break;
- }
-
- typename SizeTraits<size>::Address pc = 0x0;
- const uint8_t* offset = (const uint8_t*) pEhFrameRegion.start() +
- pOffset +
- pFDE.getPCBeginOffset();
- std::memcpy(&pc, offset, pc_size);
-
- // adjust the signed value
- bool is_signed = (fde_encoding & llvm::dwarf::DW_EH_PE_signed) != 0x0;
- switch (eh_value) {
- case DW_EH_PE_udata2:
- if (is_signed)
- pc = (pc ^ 0x8000) - 0x8000;
- break;
- case DW_EH_PE_udata4:
- if (is_signed && size > 32)
- pc = (pc ^ 0x80000000) - 0x80000000;
- break;
- case DW_EH_PE_udata8:
- break;
- default:
- // TODO
- break;
- }
-
- // handle eh application
- switch (fde_encoding & 0x70)
- {
- case DW_EH_PE_absptr:
- break;
- case DW_EH_PE_pcrel:
- pc += m_EhFrameSect.addr() +
- pOffset +
- pFDE.getPCBeginOffset();
- break;
- case DW_EH_PE_datarel:
- // TODO
- break;
- default:
- // TODO
- break;
- }
-
- return pc;
-}
-
diff --git a/include/mcld/LD/EhFrameReader.h b/include/mcld/LD/EhFrameReader.h
new file mode 100644
index 0000000..1ac0351
--- /dev/null
+++ b/include/mcld/LD/EhFrameReader.h
@@ -0,0 +1,109 @@
+//===- EhFrameReader.h ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_EH_FRAME_READER_H
+#define MCLD_EH_FRAME_READER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Support/MemoryRegion.h>
+
+namespace mcld {
+
+class Input;
+class EhFrame;
+class LDSection;
+
+/** \class EhFrameReader
+ * \brief EhFrameReader reads .eh_frame section
+ *
+ * EhFrameReader is responsible to parse the input eh_frame sections and create
+ * the corresponding CIE and FDE entries.
+ */
+class EhFrameReader
+{
+public:
+ typedef const uint8_t* ConstAddress;
+ typedef uint8_t* Address;
+
+public:
+ /// read - read an .eh_frame section and create the corresponding
+ /// CIEs and FDEs
+ /// @param pInput [in] the Input contains this eh_frame
+ /// @param pEhFrame [inout] the input eh_frame
+ /// @return if we read all CIEs and FDEs successfully, return true. Otherwise,
+ /// return false;
+ template<size_t BITCLASS, bool SAME_ENDIAN>
+ bool read(Input& pInput, EhFrame& pEhFrame);
+
+private:
+ enum TokenKind {
+ CIE,
+ FDE,
+ Terminator,
+ Unknown,
+ NumOfTokenKinds
+ };
+
+ enum State {
+ Q0,
+ Q1,
+ Accept,
+ NumOfStates = 2,
+ Reject = -1
+ };
+
+ struct Token {
+ TokenKind kind;
+ size_t file_off;
+ size_t data_off;
+ uint64_t size;
+ };
+
+ /// Action - the transition function of autometa.
+ /// @param pEhFrame - the output .eh_frame section
+ /// @param pSection - the input .eh_frame section
+ /// @param pRegion - the memory region that needs to handle with.
+ typedef bool (*Action)(EhFrame& pEhFrame,
+ MemoryRegion& 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;
+
+ static bool addCIE(EhFrame& pEhFrame,
+ MemoryRegion& pRegion,
+ const Token& pToken);
+
+ static bool addFDE(EhFrame& pEhFrame,
+ MemoryRegion& pRegion,
+ const Token& pToken);
+
+ static bool addTerm(EhFrame& pEhFrame,
+ MemoryRegion& pRegion,
+ const Token& pToken);
+
+ static bool reject(EhFrame& pEhFrame,
+ MemoryRegion& pRegion,
+ const Token& pToken);
+
+};
+
+template<> bool
+EhFrameReader::read<32, true>(Input& pInput, EhFrame& pEhFrame);
+
+template<> EhFrameReader::Token
+EhFrameReader::scan<true>(ConstAddress pHandler,
+ uint64_t pOffset,
+ const MemoryRegion& pData) const;
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/ExecWriter.h b/include/mcld/LD/ExecWriter.h
index edce096..e0ea325 100644
--- a/include/mcld/LD/ExecWriter.h
+++ b/include/mcld/LD/ExecWriter.h
@@ -11,12 +11,14 @@
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <mcld/MC/MCLDOutput.h>
#include <mcld/LD/LDWriter.h>
#include <llvm/Support/system_error.h>
-namespace mcld
-{
+namespace mcld {
+
+class Module;
+class MemoryArea;
+class TargetLDBackend;
/** \class ExecWriter
* \brief ExecWriter provides an common interface for different object
@@ -32,7 +34,8 @@
public:
virtual ~ExecWriter() { }
- virtual llvm::error_code writeExecutable(Output& pOutput) = 0;
+ virtual llvm::error_code writeExecutable(Module& pModule,
+ MemoryArea& pOutput) = 0;
};
} // namespace of mcld
diff --git a/include/mcld/LD/FDE.h b/include/mcld/LD/FDE.h
deleted file mode 100644
index 760a584..0000000
--- a/include/mcld/LD/FDE.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- FDE.h --------------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_LD_FRAME_DESCRIPTION_ENTRY_H
-#define MCLD_LD_FRAME_DESCRIPTION_ENTRY_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <llvm/Support/DataTypes.h>
-#include <mcld/LD/CIE.h>
-#include <mcld/LD/RegionFragment.h>
-
-namespace mcld
-{
-
-/** \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
-{
-public:
- typedef uint32_t Offset;
-
-public:
- FDE(MemoryRegion& pRegion, const CIE& pCIE, Offset pPCBeginOffset);
- ~FDE();
-
- /// ----- observers ------ ///
- /// getCIE - the CIE corresponding to this FDE
- const CIE& getCIE() const
- { return m_CIE; }
-
- /// getPCBeginOffset - the offset to the FDE of the PC Begin field
- Offset getPCBeginOffset() const
- { return m_PCBeginOffset; }
-
-private:
- const CIE& m_CIE;
- Offset m_PCBeginOffset;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/GNUArchiveReader.h b/include/mcld/LD/GNUArchiveReader.h
index 39a9438..7a33ff4 100644
--- a/include/mcld/LD/GNUArchiveReader.h
+++ b/include/mcld/LD/GNUArchiveReader.h
@@ -15,12 +15,12 @@
#include <mcld/LD/ArchiveReader.h>
#include <mcld/LD/Archive.h>
-namespace mcld
-{
-class MemoryAreaFactory;
-class MCLDInfo;
+namespace mcld {
+
+class Module;
class Input;
class ELFObjectReader;
+class MemoryAreaFactory;
class Archive;
/** \class GNUArchiveReader
@@ -29,9 +29,7 @@
class GNUArchiveReader : public ArchiveReader
{
public:
- explicit GNUArchiveReader(MCLDInfo& pLDInfo,
- MemoryAreaFactory& pMemAreaFactory,
- ELFObjectReader& pELFObjectReader);
+ GNUArchiveReader(Module& pModule, ELFObjectReader& pELFObjectReader);
~GNUArchiveReader();
@@ -60,10 +58,12 @@
/// @param pArchiveFile - the archive that contains the needed object
/// @param pFileOffset - file offset of the member header in the archive
/// @param pNestedOffset - used when we find a nested archive
+ /// @param pMemberSize - the file size of this member
Input* readMemberHeader(Archive& pArchiveRoot,
Input& pArchiveFile,
uint32_t pFileOffset,
- uint32_t& pNestedOffset);
+ uint32_t& pNestedOffset,
+ size_t& pMemberSize);
/// readSymbolTable - read the archive symbol map (armap)
bool readSymbolTable(Archive& pArchive);
@@ -76,9 +76,18 @@
enum Archive::Symbol::Status
shouldIncludeSymbol(const llvm::StringRef& pSymName) const;
+ /// includeMember - include the object member in the given file offset, and
+ /// return the size of the object
+ /// @param pArchiveRoot - the archive root
+ /// @param pFileOffset - file offset of the member header in the archive
+ size_t includeMember(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);
+
private:
- MCLDInfo& m_LDInfo;
- MemoryAreaFactory& m_MemAreaFactory;
+ Module& m_Module;
ELFObjectReader& m_ELFObjectReader;
};
diff --git a/include/mcld/LD/GroupReader.h b/include/mcld/LD/GroupReader.h
new file mode 100644
index 0000000..39c21f8
--- /dev/null
+++ b/include/mcld/LD/GroupReader.h
@@ -0,0 +1,68 @@
+//===- GroupReader.h ------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_GROUPREADER_H
+#define MCLD_GROUPREADER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/Module.h>
+
+namespace mcld
+{
+class Archive;
+class ArchiveReader;
+class DynObjReader;
+class LinkerConfig;
+class ObjectReader;
+
+/** \class GroupReader
+ * \brief GroupReader handles the Group Node in InputTree
+ *
+ * Group Node is the root of sub-tree in InputTree which includes the iputs in
+ * the command line options --start-group and --end-group options
+ */
+class GroupReader
+{
+public:
+ GroupReader(Module& pModule,
+ ObjectReader& pObjectReader,
+ DynObjReader& pDynObjReader,
+ ArchiveReader& pArchiveReader);
+
+ ~GroupReader();
+
+ /// 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,
+ InputBuilder& pBuilder,
+ const LinkerConfig& pConfig);
+
+private:
+ /// ArchiveListEntry - record the Archive and the corresponding input iterator
+ /// of the archive node
+ struct ArchiveListEntry {
+ ArchiveListEntry(Archive& pArchive, Module::input_iterator pIterator)
+ : archive(pArchive), input(pIterator) {
+ }
+ Archive& archive;
+ Module::input_iterator input;
+ };
+
+private:
+ Module& m_Module;
+ ObjectReader& m_ObjectReader;
+ DynObjReader& m_DynObjReader;
+ ArchiveReader& m_ArchiveReader;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/LDContext.h b/include/mcld/LD/LDContext.h
index 878ba8d..3ab6ce1 100644
--- a/include/mcld/LD/LDContext.h
+++ b/include/mcld/LD/LDContext.h
@@ -22,8 +22,7 @@
class StringRef;
}
-namespace mcld
-{
+namespace mcld {
class LDSymbol;
class LDSection;
@@ -43,36 +42,20 @@
typedef SymbolTable::const_iterator const_sym_iterator;
public:
- LDContext();
-
- ~LDContext();
-
// ----- sections ----- //
- SectionTable& getSectionTable()
- { return m_SectionTable; }
+ LDContext& appendSection(LDSection& pSection);
- const SectionTable& getSectionTable() const
- { return m_SectionTable; }
+ const_sect_iterator sectBegin() const { return m_SectionTable.begin(); }
+ sect_iterator sectBegin() { return m_SectionTable.begin(); }
- sect_iterator sectBegin()
- { return m_SectionTable.begin(); }
-
- sect_iterator sectEnd()
- { return m_SectionTable.end(); }
-
- const_sect_iterator sectBegin() const
- { return m_SectionTable.begin(); }
-
- const_sect_iterator sectEnd() const
- { return m_SectionTable.end(); }
-
- LDSection* getSection(unsigned int pIdx);
+ const_sect_iterator sectEnd() const { return m_SectionTable.end(); }
+ sect_iterator sectEnd() { return m_SectionTable.end(); }
const LDSection* getSection(unsigned int pIdx) const;
-
- LDSection* getSection(const std::string& pName);
+ LDSection* getSection(unsigned int pIdx);
const LDSection* getSection(const std::string& pName) const;
+ LDSection* getSection(const std::string& pName);
size_t getSectionIdx(const std::string& pName) const;
@@ -80,20 +63,26 @@
{ return m_SectionTable.size(); }
// ----- symbols ----- //
- LDSymbol* getSymbol(unsigned int pIdx);
-
const LDSymbol* getSymbol(unsigned int pIdx) const;
-
- LDSymbol* getSymbol(const llvm::StringRef& pName);
+ LDSymbol* getSymbol(unsigned int pIdx);
const LDSymbol* getSymbol(const llvm::StringRef& pName) const;
+ LDSymbol* getSymbol(const llvm::StringRef& pName);
void addSymbol(LDSymbol* pSym)
{ m_SymTab.push_back(pSym); }
+ // ----- relocations ----- //
+ const_sect_iterator relocSectBegin() const { return m_RelocSections.begin(); }
+ sect_iterator relocSectBegin() { return m_RelocSections.begin(); }
+
+ const_sect_iterator relocSectEnd() const { return m_RelocSections.end(); }
+ sect_iterator relocSectEnd() { return m_RelocSections.end(); }
+
private:
SectionTable m_SectionTable;
SymbolTable m_SymTab;
+ SectionTable m_RelocSections;
// FIXME : maintain a map<section name, section index>
};
diff --git a/include/mcld/LD/LDFileFormat.h b/include/mcld/LD/LDFileFormat.h
index a537fb1..cd4bfd8 100644
--- a/include/mcld/LD/LDFileFormat.h
+++ b/include/mcld/LD/LDFileFormat.h
@@ -15,11 +15,10 @@
#include <cstdio>
#include <cassert>
-namespace mcld
-{
+namespace mcld {
-class MCLinker;
class LDSection;
+class ObjectBuilder;
/** \class LDFileFormat
* \brief LDFileFormat describes the common file formats.
@@ -42,6 +41,8 @@
Note,
MetaData,
Group,
+ StackNote,
+ Ignore
};
protected:
@@ -50,16 +51,11 @@
public:
virtual ~LDFileFormat();
- /// initStdSections - initialize all standard sections.
- void initStdSections(MCLinker& pLinker);
-
- /// initObjectFormat - different format, such as ELF and MachO, should
- /// implement this
- virtual void initObjectFormat(MCLinker& pLinker) = 0;
-
- /// initObjectType - different types, such as shared object, executable
- /// files, should implement this
- virtual void initObjectType(MCLinker& pLinker) = 0;
+ /// initStdSections - initialize all standard section headers.
+ /// @param [in] pBuilder The ObjectBuilder to create section headers
+ /// @param [in] pBitClass The bitclass of target backend.
+ virtual void initStdSections(ObjectBuilder& pBuilder,
+ unsigned int pBitClass) = 0;
// ----- access functions ----- //
LDSection& getText() {
diff --git a/include/mcld/LD/LDSection.h b/include/mcld/LD/LDSection.h
index 4c881ca..e57b2a6 100644
--- a/include/mcld/LD/LDSection.h
+++ b/include/mcld/LD/LDSection.h
@@ -13,14 +13,17 @@
#include <gtest.h>
#endif
-#include <llvm/ADT/StringRef.h>
#include <llvm/Support/DataTypes.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Config/Config.h>
#include <mcld/LD/LDFileFormat.h>
#include <string>
namespace mcld {
class SectionData;
+class RelocData;
+class EhFrame;
/** \class LDSection
* \brief LDSection represents a section header entry. It is a unified
@@ -28,15 +31,34 @@
*/
class LDSection
{
-public:
+private:
+ friend class Chunk<LDSection, MCLD_SECTIONS_PER_INPUT>;
+
+ LDSection();
+
LDSection(const std::string& pName,
LDFileFormat::Kind pKind,
uint32_t pType,
uint32_t pFlag,
uint64_t pSize = 0,
- uint64_t pOffset = 0,
uint64_t pAddr = 0);
+public:
+ ~LDSection();
+
+ static LDSection* Create(const std::string& pName,
+ LDFileFormat::Kind pKind,
+ uint32_t pType,
+ uint32_t pFlag,
+ uint64_t pSize = 0,
+ uint64_t pAddr = 0);
+
+ static void Destroy(LDSection*& pSection);
+
+ static void Clear();
+
+ bool hasOffset() const;
+
/// name - the name of this section.
const std::string& name() const
{ return m_Name; }
@@ -128,17 +150,29 @@
void setType(uint32_t type)
{ m_Type = type; }
- SectionData* getSectionData()
- { return m_pSectionData; }
+ // ----- SectionData ----- //
+ const SectionData* getSectionData() const { return m_Data.sect_data; }
+ SectionData* getSectionData() { return m_Data.sect_data; }
- const SectionData* getSectionData() const
- { return m_pSectionData; }
+ void setSectionData(SectionData* pSD) { m_Data.sect_data = pSD; }
- void setSectionData(SectionData* pSD)
- { m_pSectionData = pSD; }
+ bool hasSectionData() const;
- bool hasSectionData() const
- { return (NULL != m_pSectionData); }
+ // ------ RelocData ------ //
+ const RelocData* getRelocData() const { return m_Data.reloc_data; }
+ RelocData* getRelocData() { return m_Data.reloc_data; }
+
+ void setRelocData(RelocData* pRD) { m_Data.reloc_data = pRD; }
+
+ bool hasRelocData() const;
+
+ // ------ EhFrame ------ //
+ const EhFrame* getEhFrame() const { return m_Data.eh_frame; }
+ EhFrame* getEhFrame() { return m_Data.eh_frame; }
+
+ void setEhFrame(EhFrame* pEhFrame) { m_Data.eh_frame = pEhFrame; }
+
+ bool hasEhFrame() const;
/// setLink - set the sections should link with.
/// if pLink is NULL, no Link section is set.
@@ -152,7 +186,16 @@
{ m_Index = pIndex; }
private:
+ union SectOrRelocData
+ {
+ SectionData* sect_data;
+ RelocData* reloc_data;
+ EhFrame* eh_frame;
+ };
+
+private:
std::string m_Name;
+
LDFileFormat::Kind m_Kind;
uint32_t m_Type;
uint32_t m_Flag;
@@ -165,9 +208,10 @@
size_t m_Info;
LDSection* m_pLink;
- SectionData* m_pSectionData;
+ /// m_Data - the SectionData or RelocData of this section
+ SectOrRelocData m_Data;
- // the index of the file
+ /// m_Index - the index of the file
size_t m_Index;
}; // end of LDSection
diff --git a/include/mcld/LD/LDSectionFactory.h b/include/mcld/LD/LDSectionFactory.h
deleted file mode 100644
index b748a64..0000000
--- a/include/mcld/LD/LDSectionFactory.h
+++ /dev/null
@@ -1,60 +0,0 @@
-//===- LDSectionFactory.h -------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_LDSECTION_FACTORY_H
-#define MCLD_LDSECTION_FACTORY_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <string>
-
-#include <mcld/Support/GCFactory.h>
-#include <mcld/LD/LDSection.h>
-#include <mcld/LD/LDFileFormat.h>
-
-namespace mcld
-{
-
-/** \class LDSectionFactory
- * \brief provide the interface to create and delete section data for output
- */
-class LDSectionFactory : public GCFactory<LDSection, 0>
-{
-public:
- /// LDSectionFactory - the factory of LDSection
- /// pNum is the average number of the LDSections in the system.
- LDSectionFactory(size_t pNum);
- ~LDSectionFactory();
-
- /// produce - produce an empty section information.
- /// This function will create an empty SectionData and its LDSection.
- /// @param pName - The name of the section.
- /// @param pKind - The kind of the section. Used to create default section map
- /// @param pType - sh_type in ELF.
- /// @param pFlag - is the same as sh_flags.
- LDSection* produce(const std::string& pName,
- LDFileFormat::Kind pKind,
- uint32_t pType,
- uint32_t pFlag);
-
- /// destroy - destruct the LDSection.
- /// @oaram - the reference of the pointer to the destructed LDSection.
- /// after the destruction, the pointer is set to zero.
- void destroy(LDSection*& pSD);
-
- /// find - find the LDSection* in factory from the given section name.
- /// return NULL if not found.
- /// @param pName - the name of section
- LDSection* find(const std::string& pName);
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/LDSymbol.h b/include/mcld/LD/LDSymbol.h
index 99b3885..326c82f 100644
--- a/include/mcld/LD/LDSymbol.h
+++ b/include/mcld/LD/LDSymbol.h
@@ -14,12 +14,14 @@
#include <cassert>
+#include <mcld/Config/Config.h>
#include <mcld/ADT/Uncopyable.h>
#include <mcld/LD/ResolveInfo.h>
-#include <mcld/LD/FragmentRef.h>
+#include <mcld/Support/Allocators.h>
-namespace mcld
-{
+namespace mcld {
+
+class FragmentRef;
/** \class LDSymbol
* \brief LDSymbol provides a consistent abstraction for different formats
@@ -31,15 +33,25 @@
// FIXME: use SizeTrait<32> or SizeTrait<64> instead of big type
typedef ResolveInfo::SizeType SizeType;
typedef uint64_t ValueType;
- typedef FragmentRef::Offset Offset;
public:
- LDSymbol();
- LDSymbol(const LDSymbol& pCopy);
- LDSymbol& operator=(const LDSymbol& pCopy);
~LDSymbol();
+ // ----- factory method ----- //
+ static LDSymbol* Create(ResolveInfo& pResolveInfo);
+
+ static void Destroy(LDSymbol*& pSymbol);
+
+ /// Clear - This function tells MCLinker to clear all created LDSymbols.
+ static void Clear();
+
+ /// NullSymbol() - This returns a reference to a LDSymbol that represents Null
+ /// symbol.
+ static LDSymbol* Null();
+
// ----- observers ----- //
+ bool isNull() const;
+
const char* name() const {
assert(NULL != m_pResolveInfo);
return m_pResolveInfo->name();
@@ -98,8 +110,7 @@
const ResolveInfo* resolveInfo() const
{ return m_pResolveInfo; }
- bool hasFragRef() const
- { return (NULL != m_pFragRef); }
+ bool hasFragRef() const;
// ----- modifiers ----- //
void setSize(SizeType pSize) {
@@ -115,6 +126,13 @@
void setResolveInfo(const ResolveInfo& pInfo);
private:
+ friend class Chunk<LDSymbol, MCLD_SYMBOLS_PER_INPUT>;
+
+ LDSymbol();
+ LDSymbol(const LDSymbol& pCopy);
+ LDSymbol& operator=(const LDSymbol& pCopy);
+
+private:
// ----- Symbol's fields ----- //
ResolveInfo* m_pResolveInfo;
FragmentRef* m_pFragRef;
diff --git a/include/mcld/LD/LDWriter.h b/include/mcld/LD/LDWriter.h
index 78c2871..b7dd14c 100644
--- a/include/mcld/LD/LDWriter.h
+++ b/include/mcld/LD/LDWriter.h
@@ -16,10 +16,8 @@
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <mcld/Target/TargetLDBackend.h>
-namespace mcld
-{
+namespace mcld {
/** \class LDWriter
* \brief LDWriter provides the basic interfaces for all writers.
diff --git a/include/mcld/LD/Layout.h b/include/mcld/LD/Layout.h
index 4dc9897..7380b20 100644
--- a/include/mcld/LD/Layout.h
+++ b/include/mcld/LD/Layout.h
@@ -12,28 +12,29 @@
#include <gtest.h>
#endif
+#include <vector>
#include <map>
#include <llvm/ADT/ilist.h>
#include <llvm/ADT/ilist_node.h>
#include <llvm/ADT/DenseMap.h>
-#include <mcld/LD/FragmentRef.h>
#include <mcld/LD/LDSection.h>
#include <mcld/LD/SectionData.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/Support/GCFactory.h>
-namespace mcld
-{
-class MCLinker;
-class Output;
+namespace mcld {
+
+class Module;
+class FragmentRef;
+class FragmentLinker;
class TargetLDBackend;
/** \class Layout
* \brief Layout maintains the mapping between sections and fragments.
*
- * MCLinker is a fragment-based linker. But readers and target backends
+ * FragmentLinker is a fragment-based linker. But readers and target backends
* still need section information. Layout is used to maintain the mapping
* between sections and fragments. Layout helps readers and target backends
* get the input or output section information from a fragment.
@@ -41,229 +42,23 @@
class Layout
{
public:
- typedef std::vector<LDSection*> SectionOrder;
- typedef SectionOrder::iterator sect_iterator;
- typedef SectionOrder::const_iterator const_sect_iterator;
-
-public:
- /// constructor
- Layout();
-
- /// destructor
- ~Layout();
-
- /// getInputLDSection - give a Fragment, return the corresponding input
- /// LDSection*
- ///
- /// @return return NULL if the fragment is not found in input
- LDSection* getInputLDSection(const Fragment& pFrag);
-
- /// getInputLDSection - give a Fragment, return the corresponding input
- /// LDSection*
- ///
- /// @return return NULL if the fragment is not found in input
- const LDSection* getInputLDSection(const Fragment& pFrag) const;
-
- /// getFragmentRef - give a LDSection in input file and an offset, return
- /// the fragment reference.
- ///
- /// @param pInputSection - the given input section
- /// @param pOffset - the offset, cannot be larger than this input section.
- /// @return if found, return the fragment. Otherwise, return NULL.
- FragmentRef*
- getFragmentRef(const LDSection& pInputSection, uint64_t pOffset);
-
- /// getFragmentRef - give a fragment and a big offset, return the fragment
- /// reference in the section data.
- ///
- /// @param pFrag - the given fragment
- /// @param pBigOffset - the offset, can be larger than the fragment, but can
- /// not larger than this input section.
- /// @return if found, return the fragment. Otherwise, return NULL.
- FragmentRef* getFragmentRef(const Fragment& pFrag, uint64_t pBigOffset);
-
- /// getOutputOffset - Get the offset of the given fragment inside the
- /// the output's SectionData.
- uint64_t getOutputOffset(const Fragment& pFrag);
-
- /// getOutputOffset - Get the offset of the given fragment inside the
- /// the output's SectionData.
- uint64_t getOutputOffset(const Fragment& pFrag) const;
-
- /// getOutputOffset - Get the offset of the given fragment inside
- /// the output's SectionData.
- ///
- /// @return return -1 if the fragment is not found in output's SectionData.
-
- uint64_t getOutputOffset(const FragmentRef& pFragRef);
- /// getOutputOffset - Get the offset of the given fragment inside
- /// the output's SectionData.
- ///
- /// @return return -1 if the fragment is not found in output's SectionData.
- uint64_t getOutputOffset(const FragmentRef& pFragRef) const;
-
- /// getOutputLDSection - give a Fragment, return the corresponding output
- /// LDSection*
- ///
- /// @return return NULL if the fragment is not found in the output
- LDSection* getOutputLDSection(const Fragment& pFrag);
-
- /// getOutputLDSection - give a Fragment, return the corresponding output
- /// LDSection*
- ///
- /// @return return NULL if the fragment is not found in the output
- const LDSection* getOutputLDSection(const Fragment& pFrag) const;
-
// ----- modifiers ----- //
- bool layout(Output& pOutput,
- const TargetLDBackend& pBackend, const MCLDInfo& pInfo);
-
- /// addInputRange
- void addInputRange(const SectionData& pSD, const LDSection& pInputHdr);
-
- /// appendFragment - append the given Fragment to the given SectionData,
- /// and insert a AlignFragment to preserve the required align constraint if
- /// needed
- /// @return return the inserted size, i.e., the size of pFrag and alignment
- /// size if any
- uint64_t appendFragment(Fragment& pFrag, SectionData& pSD,
- uint32_t pAlignConstraint = 1);
-private:
- /** \class Range
- * \brief Range is a <input's LDSection, previous rear fragment> pair
- */
- struct Range : public llvm::ilist_node<Range>
- {
- public:
- Range();
- Range(const LDSection& pHeader);
- ~Range();
-
- public:
- LDSection* header;
- Fragment* prevRear;
- };
-
- typedef llvm::iplist<Range> RangeList;
-
- typedef std::map<const SectionData*, RangeList*> SDRangeMap;
-
- typedef GCFactory<FragmentRef, 0> FragRefFactory;
+ bool layout(Module& pModule,
+ const TargetLDBackend& pBackend,
+ const LinkerConfig& pConfig);
private:
- inline bool isFirstRange(const Range& pRange) const
- { return (NULL == pRange.prevRear); }
-
- inline bool isLastRange(const Range& pRange) const
- { return (NULL == pRange.getNextNode()); }
-
- inline bool isEmptyRange(const Range& pRange) const
- {
- if (isFirstRange(pRange)) {
- if (!pRange.header->hasSectionData() ||
- pRange.header->getSectionData()->getFragmentList().empty())
- return true;
- else
- return false;
- }
- return (NULL == pRange.prevRear->getNextNode());
- }
-
- // get the front fragment in the range.
- inline Fragment* getFront(Range& pRange) const
- {
- if (!pRange.header->hasSectionData())
- return NULL;
- if (pRange.header->getSectionData()->getFragmentList().empty())
- return NULL;
-
- if (isFirstRange(pRange))
- return &pRange.header->getSectionData()->getFragmentList().front();
-
- if (isEmptyRange(pRange))
- return NULL;
-
- return pRange.prevRear->getNextNode();
- }
-
- inline const Fragment* getFront(const Range& pRange) const
- {
- if (!pRange.header->hasSectionData())
- return NULL;
- if (pRange.header->getSectionData()->getFragmentList().empty())
- return NULL;
-
- if (isFirstRange(pRange))
- return &pRange.header->getSectionData()->getFragmentList().front();
-
- if (isEmptyRange(pRange))
- return NULL;
-
- return pRange.prevRear->getNextNode();
- }
-
- // get the rear fragment in the range.
- inline Fragment* getRear(Range& pRange) const
- {
- if (!pRange.header->hasSectionData())
- return NULL;
- if (pRange.header->getSectionData()->getFragmentList().empty())
- return NULL;
-
- if (isLastRange(pRange)) {
- if (isEmptyRange(pRange))
- return NULL;
- return &pRange.header->getSectionData()->getFragmentList().back();
- }
- return pRange.getNextNode()->prevRear;
- }
-
- inline const Fragment* getRear(const Range& pRange) const
- {
- if (!pRange.header->hasSectionData())
- return NULL;
- if (pRange.header->getSectionData()->getFragmentList().empty())
- return NULL;
-
- if (isLastRange(pRange)) {
- if (isEmptyRange(pRange))
- return NULL;
- return &pRange.header->getSectionData()->getFragmentList().back();
- }
- return pRange.getNextNode()->prevRear;
- }
-
- FragmentRef* getFragmentRef(Range &pRange, uint64_t pOffset);
-
- FragmentRef*
- getFragmentRef(Fragment& pFront, Fragment& pRear, uint64_t pOffset);
-
- bool hasLayoutOrder(const Fragment& pFragment) const
- { return (pFragment.getLayoutOrder() != ~(0U)); }
-
- bool hasLayoutOffset(const Fragment& pFragment) const
- { return (pFragment.getOffset() != ~UINT64_C(0)); }
-
- bool isValidOffset(const Fragment& pFrag, uint64_t pTargetOffset) const;
-
- void setFragmentLayoutOrder(Fragment* pFragment);
-
- void setFragmentLayoutOffset(Fragment* pFragment);
-
/// sortSectionOrder - perform sorting on m_SectionOrder to get final layout
/// ordering
- void sortSectionOrder(const Output& pOutput,
- const TargetLDBackend& pBackend,
- const MCLDInfo& pInfo);
+ void sortSectionOrder(const TargetLDBackend& pBackend,
+ const LinkerConfig& pConfig);
+
+private:
+ typedef std::vector<LDSection*> SectionOrder;
private:
/// a vector to describe the order of sections
SectionOrder m_SectionOrder;
-
- /// the map from SectionData* to its own RangeList.
- SDRangeMap m_SDRangeMap;
-
- FragRefFactory m_FragRefFactory;
};
} // namespace of mcld
diff --git a/include/mcld/LD/MsgHandler.h b/include/mcld/LD/MsgHandler.h
index d10f8a2..c89f744 100644
--- a/include/mcld/LD/MsgHandler.h
+++ b/include/mcld/LD/MsgHandler.h
@@ -17,8 +17,7 @@
#include <mcld/Support/Path.h>
#include <mcld/LD/DiagnosticEngine.h>
-namespace mcld
-{
+namespace mcld {
/** \class MsgHandler
* \brief MsgHandler controls the timing to output message.
@@ -110,18 +109,6 @@
return pHandler;
}
-//===----------------------------------------------------------------------===//
-// Inline member functions
-inline MsgHandler
-DiagnosticEngine::report(uint16_t pID, DiagnosticEngine::Severity pSeverity)
-{
- m_State.ID = pID;
- m_State.severity = pSeverity;
-
- MsgHandler result(*this);
- return result;
-}
-
} // namespace of mcld
#endif
diff --git a/include/mcld/LD/NamePool.h b/include/mcld/LD/NamePool.h
index 1c0f8b3..12b4b91 100644
--- a/include/mcld/LD/NamePool.h
+++ b/include/mcld/LD/NamePool.h
@@ -19,14 +19,11 @@
#include <mcld/ADT/HashTable.h>
#include <mcld/ADT/StringHash.h>
#include <mcld/ADT/Uncopyable.h>
-#include <mcld/LD/ResolveInfo.h>
#include <mcld/LD/Resolver.h>
-#include <mcld/LD/ResolveInfoFactory.h>
+#include <mcld/LD/ResolveInfo.h>
-namespace mcld
-{
+namespace mcld {
-class Resolver;
class StringTable;
class SymbolTableIF;
class SectionData;
@@ -39,15 +36,17 @@
class NamePool : private Uncopyable
{
public:
- typedef HashTable<ResolveInfo, StringHash<ELF>, ResolveInfoFactory> Table;
+ typedef HashTable<ResolveInfo, StringHash<ELF> > Table;
typedef size_t size_type;
public:
- NamePool(const Resolver& pResolver, size_type pSize = 3);
+ explicit NamePool(size_type pSize = 3);
+
~NamePool();
// ----- modifiers ----- //
/// createSymbol - create a symbol but do not insert into the pool.
+ /// The created symbol did not go through the path of symbol resolution.
ResolveInfo* createSymbol(const llvm::StringRef& pName,
bool pIsDyn,
ResolveInfo::Type pType,
@@ -73,12 +72,12 @@
Resolver::Result& pResult);
/// findSymbol - find the resolved output LDSymbol
- LDSymbol* findSymbol(const llvm::StringRef& pName);
const LDSymbol* findSymbol(const llvm::StringRef& pName) const;
+ LDSymbol* findSymbol(const llvm::StringRef& pName);
/// findInfo - find the resolved ResolveInfo
- ResolveInfo* findInfo(const llvm::StringRef& pName);
const ResolveInfo* findInfo(const llvm::StringRef& pName) const;
+ ResolveInfo* findInfo(const llvm::StringRef& pName);
/// insertString - insert a string
/// if the string has existed, modify pString to the existing string
@@ -98,7 +97,7 @@
size_type capacity() const;
private:
- const Resolver* m_pResolver;
+ Resolver* m_pResolver;
Table m_Table;
};
diff --git a/include/mcld/LD/ObjectReader.h b/include/mcld/LD/ObjectReader.h
index 9dbe9ac..b1355e4 100644
--- a/include/mcld/LD/ObjectReader.h
+++ b/include/mcld/LD/ObjectReader.h
@@ -16,11 +16,10 @@
#include <mcld/ADT/HashTable.h>
#include <mcld/ADT/StringHash.h>
#include <mcld/LD/ResolveInfo.h>
-#include <mcld/LD/ResolveInfoFactory.h>
-namespace mcld
-{
+namespace mcld {
+class Module;
class Input;
/** \class ObjectReader
@@ -30,18 +29,16 @@
class ObjectReader : public LDReader
{
protected:
- typedef HashTable<ResolveInfo,
- StringHash<ELF>,
- ResolveInfoFactory> GroupSignatureMap;
+ typedef HashTable<ResolveInfo, StringHash<ELF> > GroupSignatureMap;
protected:
ObjectReader()
{ }
public:
- virtual ~ObjectReader() { }
+ virtual ~ObjectReader() { f_GroupSignatureMap.clear(); }
- virtual bool readObject(Input& pFile) = 0;
+ virtual bool readHeader(Input& pFile) = 0;
virtual bool readSymbols(Input& pFile) = 0;
diff --git a/include/mcld/LD/ObjectWriter.h b/include/mcld/LD/ObjectWriter.h
index 0c48723..a84e0d3 100644
--- a/include/mcld/LD/ObjectWriter.h
+++ b/include/mcld/LD/ObjectWriter.h
@@ -13,10 +13,10 @@
#endif
#include <llvm/Support/system_error.h>
-namespace mcld
-{
+namespace mcld {
-class Output;
+class Module;
+class MemoryArea;
class GNULDBackend;
/** \class ObjectWriter
@@ -30,7 +30,7 @@
public:
virtual ~ObjectWriter();
- virtual llvm::error_code writeObject(Output& pOutput) = 0;
+ virtual llvm::error_code writeObject(Module& pModule, MemoryArea& pOutput) = 0;
};
} // namespace of mcld
diff --git a/include/mcld/LD/RelocData.h b/include/mcld/LD/RelocData.h
new file mode 100644
index 0000000..6061544
--- /dev/null
+++ b/include/mcld/LD/RelocData.h
@@ -0,0 +1,96 @@
+//===- RelocData.h --------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_RELOCATION_DATA_H
+#define MCLD_RELOCATION_DATA_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/ADT/ilist.h>
+#include <llvm/ADT/ilist_node.h>
+#include <llvm/Support/DataTypes.h>
+
+#include <mcld/Config/Config.h>
+#include <mcld/Fragment/Fragment.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Support/GCFactoryListTraits.h>
+
+
+namespace mcld {
+
+class LDSection;
+
+/** \class RelocData
+ * \brief RelocData is the special SectionData to store Relocation fragments.
+ * Since Relocations are created by GCFactory, we use GCFactoryListTraits for the
+ * FragmentList here to avoid iplist to delete Relocations.
+ */
+class RelocData
+{
+private:
+ RelocData();
+ explicit RelocData(const LDSection &pSection);
+
+ RelocData(const RelocData &); // DO NOT IMPLEMENT
+ RelocData& operator=(const RelocData &); // DO NOT IMPLEMENT
+
+public:
+ typedef llvm::iplist<Fragment,
+ GCFactoryListTraits<Fragment> > FragmentListType;
+
+ typedef FragmentListType::reference reference;
+ typedef FragmentListType::const_reference const_reference;
+
+ typedef FragmentListType::iterator iterator;
+ typedef FragmentListType::const_iterator const_iterator;
+
+ typedef FragmentListType::reverse_iterator reverse_iterator;
+ typedef FragmentListType::const_reverse_iterator const_reverse_iterator;
+
+public:
+ static RelocData* Create(const LDSection& pSection);
+
+ static RelocData* Create();
+
+ static void Destroy(RelocData*& pSection);
+
+ const LDSection &getSection() const
+ { assert(NULL != m_pSection ); return *m_pSection; }
+
+ FragmentListType &getFragmentList() { return m_Fragments; }
+ const FragmentListType &getFragmentList() const { return m_Fragments; }
+
+ size_t size() const { return m_Fragments.size(); }
+
+ bool empty() const { return m_Fragments.empty(); }
+
+ reference front () { return m_Fragments.front(); }
+ const_reference front () const { return m_Fragments.front(); }
+ reference back () { return m_Fragments.back(); }
+ const_reference back () const { return m_Fragments.back(); }
+
+ const_iterator begin () const { return m_Fragments.begin(); }
+ iterator begin () { return m_Fragments.begin(); }
+ const_iterator end () const { return m_Fragments.end(); }
+ iterator end () { return m_Fragments.end(); }
+ const_reverse_iterator rbegin() const { return m_Fragments.rbegin(); }
+ reverse_iterator rbegin() { return m_Fragments.rbegin(); }
+ const_reverse_iterator rend () const { return m_Fragments.rend(); }
+ reverse_iterator rend () { return m_Fragments.rend(); }
+
+private:
+ FragmentListType m_Fragments;
+ const LDSection* m_pSection;
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/RelocationFactory.h b/include/mcld/LD/RelocationFactory.h
index cde120f..c9f0d64 100644
--- a/include/mcld/LD/RelocationFactory.h
+++ b/include/mcld/LD/RelocationFactory.h
@@ -12,18 +12,18 @@
#include <gtest.h>
#endif
#include <mcld/Support/GCFactory.h>
-#include <mcld/LD/Relocation.h>
+#include <mcld/Fragment/Relocation.h>
-namespace mcld
-{
+namespace mcld {
class LDSymbol;
class ResolveInfo;
class FragmentRef;
+class FragmentLinker;
class Layout;
class GOT;
class TargetLDBackend;
-class MCLDInfo;
+class LinkerConfig;
/** \class RelocationFactory
* \brief RelocationFactory provides the interface for generating target
@@ -36,6 +36,7 @@
typedef Relocation::Type Type;
typedef Relocation::Address Address;
typedef Relocation::DWord DWord;
+ typedef Relocation::SWord SWord;
enum Result {
OK,
@@ -51,8 +52,7 @@
virtual ~RelocationFactory();
/// apply - general apply function
- virtual Result applyRelocation(Relocation& pRelocation,
- const MCLDInfo& pLDInfo) = 0;
+ virtual Result applyRelocation(Relocation& pRelocation) = 0;
// ----- production ----- //
/// produce - produce a relocation entry
@@ -69,10 +69,12 @@
void destroy(Relocation* pRelocation);
- void setLayout(const Layout& pLayout);
+ void setFragmentLinker(const FragmentLinker& pLinker);
// ------ observers -----//
- const Layout& getLayout() const;
+ const FragmentLinker& getFragmentLinker() const;
+
+ bool hasFragmentLinker() const;
virtual TargetLDBackend& getTarget() = 0;
@@ -81,7 +83,7 @@
virtual const char* getName(Type pType) const = 0;
private:
- const Layout* m_pLayout;
+ const FragmentLinker* m_pLinker;
};
diff --git a/include/mcld/LD/ResolveInfo.h b/include/mcld/LD/ResolveInfo.h
index 7b3cb27..2cff57e 100644
--- a/include/mcld/LD/ResolveInfo.h
+++ b/include/mcld/LD/ResolveInfo.h
@@ -15,8 +15,7 @@
#include <llvm/Support/DataTypes.h>
#include <llvm/ADT/StringRef.h>
-namespace mcld
-{
+namespace mcld {
class LDSymbol;
@@ -30,15 +29,14 @@
* - Type - what the symbol points to
* - Size - the size of the symbol point to
* - Value - the pointer to another LDSymbol
- * In order to save the memory and speed up the performance, MCLinker uses
+ * In order to save the memory and speed up the performance, FragmentLinker uses
* a bit field to store all attributes.
*
* The maximum string length is (2^16 - 1)
*/
class ResolveInfo
{
-friend class ResolveInfoFactory;
-friend class MCLinker;
+friend class FragmentLinker;
public:
typedef uint64_t SizeType;
@@ -94,6 +92,13 @@
typedef llvm::StringRef key_type;
public:
+ // ----- factory method ----- //
+ static ResolveInfo* Create(const key_type& pKey);
+
+ static void Destroy(ResolveInfo*& pInfo);
+
+ static ResolveInfo* Null();
+
// ----- modifiers ----- //
/// setRegular - set the source of the file is a regular object
void setRegular();
@@ -138,6 +143,8 @@
// ----- observers ----- //
+ bool isNull() const;
+
bool isSymbol() const;
bool isString() const;
@@ -271,7 +278,7 @@
* |length of m_Name|reserved|Symbol|Type |ELF visibility|Local|Com|Def|Dyn|Weak|
*/
uint32_t m_BitField;
- char m_Name[0];
+ char m_Name[];
};
} // namespace of mcld
diff --git a/include/mcld/LD/ResolveInfoFactory.h b/include/mcld/LD/ResolveInfoFactory.h
deleted file mode 100644
index fcadf48..0000000
--- a/include/mcld/LD/ResolveInfoFactory.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//===- ResolveInfoFactory.h -----------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_RESOLVE_INFO_FACTORY_H
-#define MCLD_RESOLVE_INFO_FACTORY_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include "mcld/LD/ResolveInfo.h"
-
-namespace mcld
-{
-
-/** \class ResolveInfoFactory
- * \brief ResolveInfoFactory creates ResolveInfos.
- */
-class ResolveInfoFactory
-{
-public:
- typedef ResolveInfo entry_type;
- typedef ResolveInfo::key_type key_type;
-
-public:
- entry_type* produce(const key_type& pKey);
- void destroy(entry_type* pEntry);
-
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/SectionData.h b/include/mcld/LD/SectionData.h
index 8666195..316d92f 100644
--- a/include/mcld/LD/SectionData.h
+++ b/include/mcld/LD/SectionData.h
@@ -16,10 +16,11 @@
#include <llvm/ADT/ilist_node.h>
#include <llvm/Support/DataTypes.h>
-#include <mcld/LD/Fragment.h>
+#include <mcld/Config/Config.h>
+#include <mcld/Support/Allocators.h>
+#include <mcld/Fragment/Fragment.h>
-namespace mcld
-{
+namespace mcld {
class LDSection;
@@ -29,11 +30,20 @@
class SectionData
{
private:
+ friend class Chunk<SectionData, MCLD_SECTIONS_PER_INPUT>;
+
+ SectionData();
+ explicit SectionData(LDSection &pSection);
+
SectionData(const SectionData &); // DO NOT IMPLEMENT
SectionData& operator=(const SectionData &); // DO NOT IMPLEMENT
public:
typedef llvm::iplist<Fragment> FragmentListType;
+
+ typedef FragmentListType::reference reference;
+ typedef FragmentListType::const_reference const_reference;
+
typedef FragmentListType::iterator iterator;
typedef FragmentListType::const_iterator const_iterator;
@@ -41,36 +51,37 @@
typedef FragmentListType::const_reverse_iterator const_reverse_iterator;
public:
- explicit SectionData(const LDSection &pSection);
+ static SectionData* Create(LDSection& pSection);
- const LDSection &getSection() const { return *m_pSection; }
+ static void Destroy(SectionData*& pSection);
- unsigned int getAlignment() const { return m_Alignment; }
- void setAlignment(unsigned int pValue) { m_Alignment = pValue; }
+ const LDSection& getSection() const { return *m_pSection; }
+ LDSection& getSection() { return *m_pSection; }
FragmentListType &getFragmentList() { return m_Fragments; }
const FragmentListType &getFragmentList() const { return m_Fragments; }
- iterator begin() { return m_Fragments.begin(); }
- const_iterator begin() const { return m_Fragments.begin(); }
-
- iterator end() { return m_Fragments.end(); }
- const_iterator end() const { return m_Fragments.end(); }
-
- reverse_iterator rbegin() { return m_Fragments.rbegin(); }
- const_reverse_iterator rbegin() const { return m_Fragments.rbegin(); }
-
- reverse_iterator rend() { return m_Fragments.rend(); }
- const_reverse_iterator rend() const { return m_Fragments.rend(); }
-
size_t size() const { return m_Fragments.size(); }
bool empty() const { return m_Fragments.empty(); }
+ reference front () { return m_Fragments.front(); }
+ const_reference front () const { return m_Fragments.front(); }
+ reference back () { return m_Fragments.back(); }
+ const_reference back () const { return m_Fragments.back(); }
+
+ const_iterator begin () const { return m_Fragments.begin(); }
+ iterator begin () { return m_Fragments.begin(); }
+ const_iterator end () const { return m_Fragments.end(); }
+ iterator end () { return m_Fragments.end(); }
+ const_reverse_iterator rbegin() const { return m_Fragments.rbegin(); }
+ reverse_iterator rbegin() { return m_Fragments.rbegin(); }
+ const_reverse_iterator rend () const { return m_Fragments.rend(); }
+ reverse_iterator rend () { return m_Fragments.rend(); }
+
private:
FragmentListType m_Fragments;
- const LDSection* m_pSection;
- unsigned int m_Alignment;
+ LDSection* m_pSection;
};
diff --git a/include/mcld/LD/SectionMap.h b/include/mcld/LD/SectionMap.h
deleted file mode 100644
index 06ae02e..0000000
--- a/include/mcld/LD/SectionMap.h
+++ /dev/null
@@ -1,103 +0,0 @@
-//===- SectionMap.h -------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_SECTION_MAP_H
-#define MCLD_SECTION_MAP_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <llvm/Support/DataTypes.h>
-#include <vector>
-#include <string>
-
-namespace mcld
-{
-
-/** \class SectionMap
- * \brief descirbe the mappings of input section's name (or prefix) to
- * its associated output section's name and offset
- */
-class SectionMap
-{
-public:
- // a mapping in SectionMap is the triple of
- // {input substr, output section's name, output section's offset}
- struct Mapping {
- std::string inputSubStr;
- std::string outputStr;
- };
-
- typedef std::vector<struct Mapping> SectionMappingTy;
-
- typedef SectionMappingTy::iterator iterator;
- typedef SectionMappingTy::const_iterator const_iterator;
-
-public:
- SectionMap();
- ~SectionMap();
-
- // get the possible output section name based on the mapping table
- // return NULL if not found
- const std::string& getOutputSectName(const std::string& pInput);
-
- // add a mapping from input substr to output name and offset.
- bool push_back(const std::string& pInput,
- const std::string& pOutput);
-
- // find - return the iterator to the mapping
- iterator find(const std::string& pInput);
-
- // at - return the pointer to the mapping
- Mapping* at(const std::string& pInput);
-
- // ----- observers ----- //
- bool empty() const
- { return m_SectMap.empty(); }
-
- size_t size() const
- { return m_SectMap.size(); }
-
- size_t capacity () const
- { return m_SectMap.capacity(); }
-
- // ----- iterators ----- //
- iterator begin()
- { return m_SectMap.begin(); }
-
- iterator end()
- { return m_SectMap.end(); }
-
- const_iterator begin() const
- { return m_SectMap.begin(); }
-
- const_iterator end() const
- { return m_SectMap.end(); }
-
- // initStdSectionMap - add common mappings of ELF and other formats
- // to SectionMap
- bool initStdSectionMap();
-
-private:
- struct SectionNameMapping {
- const char* from;
- const char* to;
- };
-
- // used to store common mappings of ELF and other formants
- static const SectionNameMapping m_StdSectionMap[];
-
- static const int m_StdSectionMapSize;
-
- SectionMappingTy m_SectMap;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/SectionMerger.h b/include/mcld/LD/SectionMerger.h
deleted file mode 100644
index a9ca0c6..0000000
--- a/include/mcld/LD/SectionMerger.h
+++ /dev/null
@@ -1,98 +0,0 @@
-//===- SectionMerger.h ----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_SECTION_MERGER_H
-#define MCLD_SECTION_MERGER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <vector>
-#include <string>
-
-#include <mcld/LD/LDSection.h>
-#include <mcld/LD/LDContext.h>
-#include <mcld/LD/SectionMap.h>
-
-namespace mcld
-{
-class MCLinker;
-
-/** \class SectionMerger
- * \brief maintain the mappings of substr of input section name to associated
- * output section (data)
- */
-class SectionMerger
-{
-public:
- struct Mapping {
- std::string inputSubStr;
- LDSection* outputSection;
- };
- typedef std::vector<Mapping> LDSectionMapTy;
-
- typedef LDSectionMapTy::iterator iterator;
- typedef LDSectionMapTy::const_iterator const_iterator;
-
-public:
- SectionMerger(SectionMap& pSectionMap, LDContext& pContext);
- ~SectionMerger();
-
- /// getOutputSectHdr - return a associated output section header
- LDSection* getOutputSectHdr(const std::string& pName);
-
- /// getOutputSectData - return a associated output section data
- SectionData* getOutputSectData(const std::string& pName);
-
- /// addMapping - add a mapping as creating one new output LDSection
- /// @param pName - a input section name
- /// @param pSection - the output LDSection*
- bool addMapping(const std::string& pName, LDSection* pSection);
-
- // ----- observers ----- //
- bool empty() const
- { return m_LDSectionMap.empty(); }
-
- size_t size() const
- { return m_LDSectionMap.size(); }
-
- size_t capacity () const
- { return m_LDSectionMap.capacity(); }
-
- // ----- iterators ----- //
- iterator find(const std::string& pName);
-
- iterator begin()
- { return m_LDSectionMap.begin(); }
-
- iterator end()
- { return m_LDSectionMap.end(); }
-
- const_iterator begin() const
- { return m_LDSectionMap.begin(); }
-
- const_iterator end() const
- { return m_LDSectionMap.end(); }
-
-private:
- /// initOutputSectMap - initialize the map from input substr to associated
- /// output LDSection*
- void initOutputSectMap();
-
-private:
- SectionMap& m_SectionNameMap;
-
- LDContext& m_Output;
-
- LDSectionMapTy m_LDSectionMap;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/SectionRules.h b/include/mcld/LD/SectionRules.h
new file mode 100644
index 0000000..bddac20
--- /dev/null
+++ b/include/mcld/LD/SectionRules.h
@@ -0,0 +1,84 @@
+//===- SectionRules.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SECTION_MERGER_H
+#define MCLD_SECTION_MERGER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <vector>
+#include <string>
+
+#include <mcld/LD/LDSection.h>
+
+namespace mcld {
+
+class Module;
+class LinkerConfig;
+class SectionMap;
+class FragmentLinker;
+
+/** \class SectionRules
+ * \brief maintain the mappings of substr of input section name to associated
+ * output section (data)
+ */
+class SectionRules
+{
+public:
+ SectionRules(const LinkerConfig& pConfig, Module& pModule);
+ ~SectionRules();
+
+ /// getMatchedSection - return the matched section by rules.
+ /// @return if we can not find the matched section, return NULL.
+ LDSection* getMatchedSection(const std::string& pName) const;
+
+ /// append - append a new mapping rule.
+ /// appendRule does not check if the appended rule is duplicated.
+ /// @param pName - the matched substring
+ /// @parap pSection - the output section
+ void append(const std::string& pName, LDSection& pSection);
+
+ size_t size () const { return m_RuleList.size(); }
+ bool empty() const { return m_RuleList.empty(); }
+
+ /// initOutputSectMap - initialize the map from input substr to associated
+ /// output LDSection*
+ void initOutputSectMap();
+
+private:
+ struct Rule {
+ public:
+ Rule(const std::string& pSubStr, LDSection* pTarget);
+
+ public:
+ uint32_t hash;
+ std::string substr;
+ LDSection* target;
+ };
+
+ typedef std::vector<Rule> RuleList;
+
+ typedef RuleList::iterator iterator;
+ typedef RuleList::const_iterator const_iterator;
+
+private:
+ // ----- iterators ----- //
+ const_iterator find(const std::string& pName) const;
+ iterator find(const std::string& pName);
+
+private:
+ const SectionMap& m_SectionNameMap;
+ Module& m_Module;
+ RuleList m_RuleList;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/SectionSymbolSet.h b/include/mcld/LD/SectionSymbolSet.h
new file mode 100644
index 0000000..3ec590f
--- /dev/null
+++ b/include/mcld/LD/SectionSymbolSet.h
@@ -0,0 +1,81 @@
+//===- SectionSymbolSet.h -------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SECTIONSYMBOLSET_H
+#define MCLD_SECTIONSYMBOLSET_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <mcld/ADT/HashTable.h>
+#include <mcld/ADT/HashEntry.h>
+#include <mcld/MC/SymbolCategory.h>
+
+namespace mcld
+{
+
+class LDSection;
+class NamePool;
+class LDSymbol;
+
+/** \class SectionSymbolSet
+ * \brief SectionSymbolSet contains the section symbols defined by linker for
+ * the output sections
+ */
+class SectionSymbolSet
+{
+public:
+ typedef SymbolCategory SymbolTable;
+
+public:
+ SectionSymbolSet();
+ ~SectionSymbolSet();
+
+ /// add - create and add an section symbol for the output
+ /// LDSection
+ bool add(LDSection& pOutSect, NamePool& pNamePool);
+
+ /// finalize - set section symbols' fragmentRef and push it into the output
+ /// symbol table
+ bool finalize(LDSection& pOutSect, SymbolTable& pSymTab);
+
+ /// get - get the section symbol for section pOutpSect
+ LDSymbol* get(const LDSection& pOutSect);
+ const LDSymbol* get(const LDSection& pOutSect) const;
+
+private:
+ /// sectCompare - hash compare function for LDSection*
+ struct SectCompare
+ {
+ bool operator()(const LDSection* X, const LDSection* Y) const
+ { return (X==Y); }
+ };
+
+ /// SectPtrHash - hash function for LDSection*
+ struct SectPtrHash
+ {
+ size_t operator()(const LDSection* pKey) const
+ {
+ return (unsigned((uintptr_t)pKey) >> 4) ^
+ (unsigned((uintptr_t)pKey) >> 9);
+ }
+ };
+
+ typedef HashEntry<const LDSection*, LDSymbol*, SectCompare> SectHashEntryType;
+ typedef HashTable<SectHashEntryType,
+ SectPtrHash,
+ EntryFactory<SectHashEntryType> > SectHashTableType;
+
+private:
+ SectHashTableType* m_pSectionSymbolMap;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/LD/StringUnorderedMap.h b/include/mcld/LD/StringUnorderedMap.h
deleted file mode 100644
index 05788aa..0000000
--- a/include/mcld/LD/StringUnorderedMap.h
+++ /dev/null
@@ -1,225 +0,0 @@
-//===- StringUnorderedMap.h -----------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_SEARCH_TABLE_H
-#define MCLD_SEARCH_TABLE_H
-#include <vector>
-// For std::allocate.
-#include <memory>
-// For uint32_t.
-#include <stdint.h>
-#include <cassert>
-// For memset.
-#include <cstring>
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-/* FIXME: Move StringUnorderedMap under ADT. */
-
-namespace mcld
-{
-
-struct StringUnorderedMapDefaultHash
-{
- size_t operator()(const char *pStr) {
- size_t hashVal = 31;
- while (*pStr)
- hashVal = hashVal * 131 + (*pStr++);
- return hashVal;
- }
-};
-
-template<typename ValueType,
- typename KeyType>
-struct StringUnorderedMapEntryInit
-{
- template <typename InitType>
- void operator()(KeyType &pKey, ValueType &pValue,
- const KeyType &pStr, InitType pInitVal) {
- ::new ((void*)&pKey) KeyStorageType(pStr);
- ::new ((void*)&pValue) ValueType(pInitVal);
- }
-};
-
-uint32_t findNextPrime(uint32_t x);
-
-/** \class StringUnorderedMap
- * \brief The most simple hash of linked list version.
- *
- * \see
- */
-template<typename KeyType,
- typename ValueType,
- typename KeyCompareFunctor,
- typename HashFunction = StringUnorderedMapDefaultHash,
- typename Allocator = std::allocator<std::pair<KeyType, ValueType> > >
-class StringUnorderedMap
-{
-public:
- explicit StringUnorderedMap(size_t pCapacity = 17)
- : m_Impl(pCapacity)
- {}
-
- ~StringUnorderedMap();
-
- void reserve(size_t pCapacity);
-
- ValueType &getOrCreate(const KeyType &pStr, const ValueType &pInitVal);
-
- ValueType &getOrCreate(const KeyType &pStr);
-
- bool empty()
- { return m_Size == 0; }
-
- size_t capacity() const
- { return m_Capacity; }
-
- void clear();
-
-private:
- struct HashEntry {
- size_t hashVal;
- std::pair<KeyType, ValueType>
- HashEntry *next;
- };
- typedef Allocator::template rebind<HashEntry>::other HashEntryAllocator;
- void rehash(size_t pCapacity);
-
-private:
- size_t m_Capacity;
- size_t m_Size;
- // array of pointers to hash entries
- HashEntry **m_HashTable;
- HashEntryAllocator m_HashEntryAllocator;
-};
-
-
-// =================================implementation============================
-// StringUnorderedMap::StringUnorderedMapImpl
-template<typename ValueType,
- typename KeyStorageType,
- typename HashFunction,
- typename Allocator>
-StringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>::
-StringUnorderedMapImpl::StringUnorderedMapImpl(size_t pCapacity)
- : m_Capacity(0), m_Size(0), m_HashTable(0)
-{
- this->reserve(pCapacity);
-}
-
-template<typename ValueType,
- typename KeyStorageType,
- typename HashFunction,
- typename Allocator>
-void
-StringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>::
-StringUnorderedMapImpl::reserve(size_t pCapacity)
-{
- if (pCapacity < this->m_Capacity)
- return;
- size_t nextSize = findNextPrime(static_cast<uint32_t>(pCapacity));
- // FIXME: Error handling.
- assert(nextSize > this->m_Capacity && "findNextPrime error.");
- if (this->m_Capacity != nextSize)
- this->rehash(nextSize);
-}
-
-template<typename ValueType,
- typename KeyStorageType,
- typename HashFunction,
- typename Allocator>
-void
-StringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>::
-StringUnorderedMapImpl::rehash(size_t pCapacity)
-{
- HashEntry **tmpTable = new HashEntry*[pCapacity];
- std::memset(tmpTable, 0, pCapacity * sizeof(HashEntry*));
- if (this->m_HashTable) {
- for (size_t i = 0; i < this->m_Capacity; ++i)
- for (HashEntry *j = this->m_HashTable[i]; j != 0; ) {
- HashEntry *nextJ = j->next;
- j->next = tmpTable[j->hashVal % pCapacity];
- tmpTable[j->hashVal % pCapacity] = j;
- j = nextJ;
- }
- delete[] m_HashTable;
- }
- this->m_Capacity = pCapacity;
- this->m_HashTable = tmpTable;
-}
-
-template<typename ValueType,
- typename KeyStorageType,
- typename HashFunction,
- typename Allocator>
-template<typename InitType>
-ValueType &
-StringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>::
-StringUnorderedMapImpl::getOrCreate(const KeyType &pStr, ValueType &pInitVal)
-{
- HashFunction hash;
- size_t hashVal = hash(pStr);
- HashEntry *&head = this->m_HashTable[hashVal % this->m_Capacity];
-
- HashEntry *ans = 0;
- for(HashEntry *ptr = head; ptr != 0; ptr = ptr->next)
- if(hashVal == ptr->hashVal && pStr.equals(ptr->str)) {
- ans = ptr;
- break;
- }
- if (ans == 0) {
- ans = this->allocate(1);
- ans->hashVal = hashVal;
- StringUnorderedMapEntryInit<ValueType, KeyStorageType> init;
- init(ans->str, ans->value, pStr, pInitVal);
- ans->next = head;
- head = ans;
- ++m_Size;
- if(this->m_Size * 4LL >= this->m_Capacity * 3LL) // load factor = 0.75
- this->reserve(this->m_Capacity+1);
- }
-
- return ans->value;
-}
-
-template<typename ValueType,
- typename KeyStorageType,
- typename HashFunction,
- typename Allocator>
-void
-StringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>::
-StringUnorderedMapImpl::clear()
-{
- if (this->m_HashTable) {
- for (size_t i = 0; i < this->m_Capacity; ++i)
- for (HashEntry *j = this->m_HashTable[i]; j != 0; ) {
- HashEntry *nextJ = j->next;
- this->destroy(j);
- this->deallocate(j, 1);
- j = nextJ;
- }
- delete[] m_HashTable;
- }
-}
-
-
-template<typename ValueType,
- typename KeyStorageType,
- typename HashFunction,
- typename Allocator>
-StringUnorderedMap<ValueType, KeyStorageType, HashFunction, Allocator>::
-StringUnorderedMapImpl::~StringUnorderedMapImpl()
-{
- this->clear();
-}
-
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/LD/StubFactory.h b/include/mcld/LD/StubFactory.h
new file mode 100644
index 0000000..00a65ec
--- /dev/null
+++ b/include/mcld/LD/StubFactory.h
@@ -0,0 +1,65 @@
+//===- StubFactory.h ------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MCLD_LD_STUB_FACTORY_H
+#define MCLD_LD_STUB_FACTORY_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <vector>
+
+namespace mcld
+{
+
+class Stub;
+class Relocation;
+class RelocationFactory;
+class BranchIslandFactory;
+class FragmentLinker;
+
+/** \class StubFactory
+ * \brief the clone factory of Stub
+ *
+ */
+class StubFactory
+{
+public:
+ StubFactory();
+
+ ~StubFactory();
+
+ /// addPrototype - register a stub prototype
+ void addPrototype(Stub* pPrototype);
+
+ /// create - create a stub if needed, otherwise return NULL
+ Stub* create(Relocation& pReloc,
+ uint64_t pTargetSymValue,
+ FragmentLinker& pLinker,
+ RelocationFactory& pRelocFactory,
+ BranchIslandFactory& pBRIslandFactory);
+
+private:
+ /// findPrototype - find if there is a registered stub prototype for the given
+ /// relocation
+ Stub* findPrototype(const Relocation& pReloc,
+ const uint64_t pSource,
+ uint64_t pTargetSymValue);
+
+private:
+ typedef std::vector<Stub*> StubPoolType;
+
+private:
+ StubPoolType m_StubPool; // stub pool
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/include/mcld/LD/TextDiagnosticPrinter.h b/include/mcld/LD/TextDiagnosticPrinter.h
index 278c00f..3e7d4c4 100644
--- a/include/mcld/LD/TextDiagnosticPrinter.h
+++ b/include/mcld/LD/TextDiagnosticPrinter.h
@@ -17,7 +17,7 @@
namespace mcld
{
-class MCLDInfo;
+class LinkerConfig;
/** \class TextDiagnosticPrinter
* \brief The plain, text-based DiagnosticPrinter.
@@ -25,7 +25,7 @@
class TextDiagnosticPrinter : public DiagnosticPrinter
{
public:
- TextDiagnosticPrinter(llvm::raw_ostream& pOStream, const MCLDInfo& pLDInfo);
+ TextDiagnosticPrinter(llvm::raw_ostream& pOStream, const LinkerConfig& pConfig);
virtual ~TextDiagnosticPrinter();
@@ -34,13 +34,13 @@
virtual void handleDiagnostic(DiagnosticEngine::Severity pSeverity,
const Diagnostic& pInfo);
- virtual void beginInput(const Input& pInput, const MCLDInfo& pLDInfo);
+ virtual void beginInput(const Input& pInput, const LinkerConfig& pConfig);
virtual void endInput();
private:
llvm::raw_ostream& m_OStream;
- const MCLDInfo& m_LDInfo;
+ const LinkerConfig& m_Config;
const Input* m_pInput;
};
diff --git a/include/mcld/Linker.h b/include/mcld/Linker.h
new file mode 100644
index 0000000..891372c
--- /dev/null
+++ b/include/mcld/Linker.h
@@ -0,0 +1,75 @@
+//===- Linker.h -----------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_LINKER_H
+#define MCLD_LINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <string>
+
+namespace mcld {
+
+class Module;
+class LinkerConfig;
+
+class Target;
+class TargetLDBackend;
+
+class IRBuilder;
+class ObjectLinker;
+
+class FileHandle;
+class MemoryArea;
+
+/** \class Linker
+* \brief Linker is a modular linker.
+*/
+class Linker
+{
+public:
+ Linker();
+
+ ~Linker();
+
+ bool config(LinkerConfig& pConfig);
+
+ bool link(Module& pModule, IRBuilder& pBuilder);
+
+ bool emit(MemoryArea& pOutput);
+
+ bool emit(const std::string& pPath);
+
+ bool emit(int pFileDescriptor);
+
+ bool reset();
+
+private:
+ bool initTarget();
+
+ bool initBackend();
+
+ bool initEmulator();
+
+ bool initOStream();
+
+private:
+ LinkerConfig* m_pConfig;
+ Module* m_pModule;
+ IRBuilder* m_pIRBuilder;
+
+ const Target* m_pTarget;
+ TargetLDBackend* m_pBackend;
+ ObjectLinker* m_pObjLinker;
+};
+
+} // namespace of MC Linker
+
+#endif
+
diff --git a/include/mcld/LinkerConfig.h b/include/mcld/LinkerConfig.h
new file mode 100644
index 0000000..7d52819
--- /dev/null
+++ b/include/mcld/LinkerConfig.h
@@ -0,0 +1,90 @@
+//===- LinkerConfig.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_LINKER_CONFIG_H
+#define MCLD_LINKER_CONFIG_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/ADT/Triple.h>
+
+#include <mcld/GeneralOptions.h>
+#include <mcld/ScriptOptions.h>
+#include <mcld/BitcodeOption.h>
+#include <mcld/AttributeOption.h>
+#include <mcld/Support/Path.h>
+
+#include <string>
+
+namespace mcld {
+
+/** \class LinkerConfig
+ * \brief LinkerConfig is composed of argumments of MCLinker.
+ * options() - the general options
+ * scripts() - the script options
+ * bitcode() - the bitcode being linked
+ * attribute() - the attribute options
+ */
+class LinkerConfig
+{
+public:
+ enum CodeGenType {
+ Unknown,
+ Object,
+ DynObj,
+ Exec,
+ External
+ };
+
+public:
+ LinkerConfig();
+
+ explicit LinkerConfig(const std::string &pTripleString);
+
+ ~LinkerConfig();
+
+ const GeneralOptions& options() const { return m_Options; }
+ GeneralOptions& options() { return m_Options; }
+
+ const ScriptOptions& scripts() const { return m_Scripts; }
+ ScriptOptions& scripts() { return m_Scripts; }
+
+ const BitcodeOption& bitcode() const { return m_Bitcode; }
+ BitcodeOption& bitcode() { return m_Bitcode; }
+
+ const AttributeOption& attribute() const { return m_Attribute; }
+ AttributeOption& attribute() { return m_Attribute; }
+
+ CodeGenType codeGenType() const { return m_CodeGenType; }
+
+ void setCodeGenType(CodeGenType pType) { m_CodeGenType = pType; }
+
+ const llvm::Triple& triple() const { return m_Triple; }
+
+ void setTriple(const std::string& pTriple);
+
+ void setTriple(const llvm::Triple& pTriple);
+
+ static const char* version();
+
+private:
+ // ----- General Options ----- //
+ GeneralOptions m_Options;
+ ScriptOptions m_Scripts;
+ BitcodeOption m_Bitcode;
+ AttributeOption m_Attribute;
+
+ llvm::Triple m_Triple;
+ CodeGenType m_CodeGenType;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/MC/MCLDAttribute.h b/include/mcld/MC/Attribute.h
similarity index 90%
rename from include/mcld/MC/MCLDAttribute.h
rename to include/mcld/MC/Attribute.h
index f7f9f97..11f6d26 100644
--- a/include/mcld/MC/MCLDAttribute.h
+++ b/include/mcld/MC/Attribute.h
@@ -1,4 +1,4 @@
-//===- MCLDAttribute.h ----------------------------------------------------===//
+//===- Attribute.h --------------------------------------------------------===//
//
// The MCLinker Project
//
@@ -11,12 +11,10 @@
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <vector>
-#include <string>
-namespace mcld
-{
-class AttributeFactory;
+namespace mcld {
+
+class AttributeSet;
/** \class AttributeBase
* \brief AttributeBase provides the real storage for attributes of options.
@@ -73,6 +71,7 @@
// represent GNU ld -call_shared option
bool isDynamic() const
{ return !m_Static; }
+
public:
bool m_WholeArchive : 1;
bool m_AsNeeded : 1;
@@ -175,19 +174,19 @@
* AttributeProxy hides the reality of sharing. An input file can change
* its attribute without explicit searching of existing attributes
* as it has a private ownership of the attribute. AttributeProxy does
- * the searching in the AttributeFactory and changes the pointer of
+ * the searching in the AttributeSet and changes the pointer of
* the attribute of the input file. If the searching fails, AttributeProxy
- * requests a new attribute from the AttributeFactory.
+ * requests a new attribute from the AttributeSet.
*/
class AttributeProxy
{
-private:
- friend class AttributeFactory;
+public:
+ AttributeProxy(AttributeSet& pParent,
+ const Attribute& pBase,
+ const AttrConstraint& pConstraint);
- explicit AttributeProxy(AttributeFactory& pParent, Attribute& pBase);
~AttributeProxy();
-public:
// ----- observers ----- //
bool isWholeArchive() const;
@@ -199,9 +198,6 @@
bool isDynamic() const;
- Attribute* attr()
- { return m_pBase; }
-
const Attribute* attr() const
{ return m_pBase; }
@@ -215,15 +211,12 @@
void setStatic();
void setDynamic();
-private:
- AttributeProxy* clone() const;
-
- void change(Attribute* pBase)
- { m_pBase = pBase; }
+ AttributeProxy& assign(Attribute* pBase);
private:
- AttributeFactory &m_AttrPool;
- Attribute *m_pBase;
+ AttributeSet &m_AttrPool;
+ const Attribute *m_pBase;
+ const AttrConstraint& m_Constraint;
};
diff --git a/include/mcld/MC/AttributeFactory.h b/include/mcld/MC/AttributeFactory.h
deleted file mode 100644
index 0af1328..0000000
--- a/include/mcld/MC/AttributeFactory.h
+++ /dev/null
@@ -1,99 +0,0 @@
-//===- AttributeFactory.h -------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_ATTRIBUTE_FACTORY_H
-#define MCLD_ATTRIBUTE_FACTORY_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/ADT/Uncopyable.h>
-#include <mcld/MC/MCLDAttribute.h>
-
-namespace mcld
-{
-
-/** \class AttributeFactory
- * \brief AttributeFactory contructs the AttributeProxys.
- *
- * Since the number of AttributeProxys is usually small, sequential search
- * on a small vector is enough.
- */
-class AttributeFactory : private Uncopyable
-{
-private:
- typedef std::vector<Attribute*> AttrSet;
-
-public:
- typedef AttrSet::iterator iterator;
- typedef AttrSet::const_iterator const_iterator;
-
-public:
- AttributeFactory();
- explicit AttributeFactory(size_t pNum);
- ~AttributeFactory();
-
- // reserve - reserve the memory space for attributes
- // @param pNum the number of reserved attributes
- void reserve(size_t pNum);
-
- // predefined - return the predefined attribute
- Attribute& predefined();
- const Attribute& predefined() const;
-
- // constraint - return the constraint of attributes
- AttrConstraint& constraint()
- { return m_Constraint; }
-
- const AttrConstraint& constraint() const
- { return m_Constraint; }
-
- // produce - produce a attribute, but do not record it yet.
- // the produced attribute is identical to the pre-defined attribute.
- AttributeProxy* produce();
-
- // last - the last touched attribute.
- AttributeProxy& last();
- const AttributeProxy& last() const;
-
- // exists- return the recorded attribute whose content is identical to the
- // input attribute.
- Attribute *exists(const Attribute& pAttr) const;
-
- // record - record the attribute no mater if it has been recorded.
- void record(Attribute& pAttr);
-
- // ----- observers ----- //
- size_t size() const
- { return m_AttrSet.size(); }
-
- bool empty() const
- { return m_AttrSet.empty(); }
-
- // ----- iterators ----- //
- iterator begin()
- { return m_AttrSet.begin(); }
-
- iterator end()
- { return m_AttrSet.end(); }
-
- const_iterator begin() const
- { return m_AttrSet.begin(); }
-
- const_iterator end() const
- { return m_AttrSet.end(); }
-
-private:
- AttrSet m_AttrSet;
- AttrConstraint m_Constraint;
- AttributeProxy *m_pLast;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/MC/AttributeSet.h b/include/mcld/MC/AttributeSet.h
new file mode 100644
index 0000000..e50384d
--- /dev/null
+++ b/include/mcld/MC/AttributeSet.h
@@ -0,0 +1,62 @@
+//===- AttributeSet.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_ATTRIBUTE_SET_H
+#define MCLD_ATTRIBUTE_SET_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/ADT/Uncopyable.h>
+#include <vector>
+
+namespace mcld {
+
+class Attribute;
+
+/** \class AttributeSet
+ * \brief AttributeSet is a set of Attribute.
+ *
+ * Clients delegates Attributes to AttributeSet. AttributeSet deletes delegated
+ * Attributes during destruction.
+ */
+class AttributeSet : private Uncopyable
+{
+private:
+ typedef std::vector<Attribute*> AttrSet;
+
+public:
+ typedef AttrSet::iterator iterator;
+ typedef AttrSet::const_iterator const_iterator;
+
+public:
+ AttributeSet(unsigned int pNum, const Attribute& pPredefined);
+
+ ~AttributeSet();
+
+ // ----- iterators ----- //
+ const_iterator begin() const { return m_AttrSet.begin(); }
+ iterator begin() { return m_AttrSet.begin(); }
+ const_iterator end () const { return m_AttrSet.end(); }
+ iterator end () { return m_AttrSet.end(); }
+
+ // exists- return the recorded attribute whose content is identical to the
+ // input attribute.
+ Attribute *exists(const Attribute& pAttr) const;
+
+ // record - record the attribute no mater if it has been recorded.
+ void record(Attribute& pAttr);
+
+private:
+ AttrSet m_AttrSet;
+ const Attribute& m_Predefined;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/MC/CommandAction.h b/include/mcld/MC/CommandAction.h
new file mode 100644
index 0000000..a0ff909
--- /dev/null
+++ b/include/mcld/MC/CommandAction.h
@@ -0,0 +1,165 @@
+//===- CommandAction.h ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MC_COMMAND_ACTION_H
+#define MCLD_MC_COMMAND_ACTION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <string>
+#include <mcld/Support/Path.h>
+#include <mcld/MC/InputAction.h>
+
+namespace mcld {
+
+class SearchDirs;
+class InputBuilder;
+
+//===----------------------------------------------------------------------===//
+// Derived InputAction
+//===----------------------------------------------------------------------===//
+/// InputFileAction
+class InputFileAction : public InputAction
+{
+public:
+ explicit InputFileAction(unsigned int pPosition, const sys::fs::Path &pPath);
+
+ const sys::fs::Path& path() const { return m_Path; }
+
+ bool activate(InputBuilder&) const;
+
+private:
+ sys::fs::Path m_Path;
+};
+
+/// NamespecAction
+class NamespecAction : public InputAction
+{
+public:
+ NamespecAction(unsigned int pPosition,
+ const std::string &pNamespec,
+ SearchDirs& pSearchDirs);
+
+ const std::string &namespec() const { return m_Namespec; }
+
+ bool activate(InputBuilder&) const;
+
+private:
+ std::string m_Namespec;
+ SearchDirs& m_SearchDirs;
+};
+
+/// BitcodeAction
+class BitcodeAction : public InputAction
+{
+public:
+ BitcodeAction(unsigned int pPosition, const sys::fs::Path &pPath);
+
+ const sys::fs::Path& path() const { return m_Path; }
+
+ bool activate(InputBuilder&) const;
+
+private:
+ sys::fs::Path m_Path;
+};
+
+/// StartGroupAction
+class StartGroupAction : public InputAction
+{
+public:
+ explicit StartGroupAction(unsigned int pPosition);
+
+ bool activate(InputBuilder&) const;
+};
+
+/// EndGroupAction
+class EndGroupAction : public InputAction
+{
+public:
+ explicit EndGroupAction(unsigned int pPosition);
+
+ bool activate(InputBuilder&) const;
+};
+
+/// WholeArchiveAction
+class WholeArchiveAction : public InputAction
+{
+public:
+ explicit WholeArchiveAction(unsigned int pPosition);
+
+ bool activate(InputBuilder&) const;
+};
+
+/// NoWholeArchiveAction
+class NoWholeArchiveAction : public InputAction
+{
+public:
+ explicit NoWholeArchiveAction(unsigned int pPosition);
+
+ bool activate(InputBuilder&) const;
+};
+
+/// AsNeededAction
+class AsNeededAction : public InputAction
+{
+public:
+ explicit AsNeededAction(unsigned int pPosition);
+
+ bool activate(InputBuilder&) const;
+};
+
+/// NoAsNeededAction
+class NoAsNeededAction : public InputAction
+{
+public:
+ explicit NoAsNeededAction(unsigned int pPosition);
+
+ bool activate(InputBuilder&) const;
+};
+
+/// AddNeededAction
+class AddNeededAction : public InputAction
+{
+public:
+ explicit AddNeededAction(unsigned int pPosition);
+
+ bool activate(InputBuilder&) const;
+};
+
+/// NoAddNeededAction
+class NoAddNeededAction : public InputAction
+{
+public:
+ explicit NoAddNeededAction(unsigned int pPosition);
+
+ bool activate(InputBuilder&) const;
+};
+
+/// BDynamicAction
+class BDynamicAction : public InputAction
+{
+public:
+ explicit BDynamicAction(unsigned int pPosition);
+
+ bool activate(InputBuilder&) const;
+};
+
+/// BStaticAction
+class BStaticAction : public InputAction
+{
+public:
+ explicit BStaticAction(unsigned int pPosition);
+
+ bool activate(InputBuilder&) const;
+};
+
+} // end of namespace mcld
+
+#endif
+
diff --git a/include/mcld/MC/FileAction.h b/include/mcld/MC/FileAction.h
new file mode 100644
index 0000000..4644405
--- /dev/null
+++ b/include/mcld/MC/FileAction.h
@@ -0,0 +1,53 @@
+//===- FileAction.h -------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MC_FILE_ACTION_H
+#define MCLD_MC_FILE_ACTION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/MC/InputAction.h>
+#include <mcld/Support/FileHandle.h>
+
+namespace mcld {
+
+class ContextFactory;
+class MemoryAreaFactory;
+
+/** \class ContextAction
+ * \brief ContextAction is a command object to create input's LDContext.
+ */
+class ContextAction : public InputAction
+{
+public:
+ explicit ContextAction(unsigned int pPosition);
+
+ bool activate(InputBuilder& pBuilder) const;
+};
+
+/** \class MemoryAreaAction
+ * \brief MemoryAreaAction is a command object to create input's MemoryArea.
+ */
+class MemoryAreaAction : public InputAction
+{
+public:
+ MemoryAreaAction(unsigned int pPosition,
+ FileHandle::OpenMode pMode,
+ FileHandle::Permission pPerm = FileHandle::System);
+
+ bool activate(InputBuilder& pBuilder) const;
+
+private:
+ FileHandle::OpenMode m_Mode;
+ FileHandle::Permission m_Permission;
+};
+
+} // end of namespace mcld
+
+#endif
+
diff --git a/include/mcld/MC/InputAction.h b/include/mcld/MC/InputAction.h
new file mode 100644
index 0000000..fb7d660
--- /dev/null
+++ b/include/mcld/MC/InputAction.h
@@ -0,0 +1,53 @@
+//===- InputAction.h ------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MC_INPUT_ACTION_H
+#define MCLD_MC_INPUT_ACTION_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+namespace mcld {
+
+class SearchDirs;
+class InputBuilder;
+
+//===----------------------------------------------------------------------===//
+// Base InputAction
+//===----------------------------------------------------------------------===//
+/** \class InputAction
+ * \brief InputAction is a command object to construct mcld::InputTree.
+ */
+class InputAction
+{
+protected:
+ explicit InputAction(unsigned int pPosition);
+
+public:
+ virtual ~InputAction();
+
+ virtual bool activate(InputBuilder&) const = 0;
+
+ unsigned int position() const { return m_Position; }
+
+ bool operator<(const InputAction& pOther) const
+ { return (position() < pOther.position()); }
+
+private:
+ InputAction(); // DO_NOT_IMPLEMENT
+ InputAction(const InputAction& ); // DO_NOT_IMPLEMENT
+ InputAction& operator=(const InputAction& ); // DO_NOT_IMPLEMENT
+
+private:
+ unsigned int m_Position;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/MC/InputBuilder.h b/include/mcld/MC/InputBuilder.h
new file mode 100644
index 0000000..0301c15
--- /dev/null
+++ b/include/mcld/MC/InputBuilder.h
@@ -0,0 +1,141 @@
+//===- InputBuilder.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MC_INPUT_BUILDER_H
+#define MCLD_MC_INPUT_BUILDER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <string>
+#include <stack>
+
+#include <mcld/InputTree.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/Support/FileHandle.h>
+
+namespace mcld {
+
+class LinkerConfig;
+class InputFactory;
+class ContextFactory;
+class MemoryAreaFactory;
+class AttrConstraint;
+class raw_mem_ostream;
+
+/** \class InputBuilder
+ * \brief InputBuilder recieves InputActions and build the InputTree.
+ *
+ * InputBuilder build input tree and inputs.
+ */
+class InputBuilder
+{
+public:
+ explicit InputBuilder(const LinkerConfig& pConfig);
+
+ InputBuilder(const LinkerConfig& pConfig,
+ InputFactory& pInputFactory,
+ ContextFactory& pContextFactory,
+ MemoryAreaFactory& pMemoryFactory,
+ bool pDelegate = true);
+
+ virtual ~InputBuilder();
+
+ // ----- input tree operations ----- //
+ const InputTree& getCurrentTree() const;
+ InputTree& getCurrentTree();
+
+ void setCurrentTree(InputTree& pInputTree);
+
+ // ----- root of input tree ----- //
+ const InputTree::iterator& getCurrentNode() const { return m_Root; }
+ InputTree::iterator& getCurrentNode() { return m_Root; }
+
+ template<InputTree::Direction DIRECTION>
+ InputTree& createNode(const std::string& pName,
+ const sys::fs::Path& pPath,
+ unsigned int pType = Input::Unknown);
+
+ // ----- input operations ----- //
+ Input* createInput(const std::string& pName,
+ const sys::fs::Path& pPath,
+ unsigned int pType = Input::Unknown,
+ off_t pFileOffset = 0);
+
+ bool setContext(Input& pInput, bool pCheck = true);
+
+ bool setMemory(Input& pInput,
+ FileHandle::OpenMode pMode,
+ FileHandle::Permission pPerm = FileHandle::System);
+
+ bool setMemory(Input& pInput, void* pMemBuffer, size_t pSize);
+
+ InputTree& enterGroup();
+
+ InputTree& exitGroup();
+
+ bool isInGroup() const;
+
+ const AttrConstraint& getConstraint() const;
+
+ const AttributeProxy& getAttributes() const;
+ AttributeProxy& getAttributes();
+
+private:
+ const LinkerConfig& m_Config;
+
+ InputFactory* m_pInputFactory;
+ MemoryAreaFactory* m_pMemFactory;
+ ContextFactory* m_pContextFactory;
+
+ InputTree* m_pCurrentTree;
+ InputTree::Mover* m_pMove;
+ InputTree::iterator m_Root;
+ std::stack<InputTree::iterator> m_ReturnStack;
+
+ bool m_bOwnFactory;
+
+};
+
+//===----------------------------------------------------------------------===//
+// Template implement
+//===----------------------------------------------------------------------===//
+template<> inline InputTree&
+InputBuilder::createNode<InputTree::Inclusive>(const std::string& pName,
+ const sys::fs::Path& pPath,
+ unsigned int pType)
+{
+ assert(NULL != m_pCurrentTree && NULL != m_pMove);
+
+ Input* input = createInput(pName, pPath, pType);
+ m_pCurrentTree->insert(m_Root, *m_pMove, *input);
+ m_pMove->move(m_Root);
+ m_pMove = &InputTree::Downward;
+
+ return *m_pCurrentTree;
+}
+
+template<> inline InputTree&
+InputBuilder::createNode<InputTree::Positional>(const std::string& pName,
+ const sys::fs::Path& pPath,
+ unsigned int pType)
+{
+ assert(NULL != m_pCurrentTree && NULL != m_pMove);
+
+ Input* input = createInput(pName, pPath, pType);
+ m_pCurrentTree->insert(m_Root, *m_pMove, *input);
+ m_pMove->move(m_Root);
+ m_pMove = &InputTree::Afterward;
+
+ return *m_pCurrentTree;
+}
+
+} // end of namespace mcld
+
+#endif
+
diff --git a/include/mcld/MC/InputFactory.h b/include/mcld/MC/InputFactory.h
index 5dc99c4..d644222 100644
--- a/include/mcld/MC/InputFactory.h
+++ b/include/mcld/MC/InputFactory.h
@@ -11,13 +11,14 @@
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include "mcld/Support/GCFactory.h"
-#include "mcld/MC/MCLDInput.h"
+#include <mcld/Support/GCFactory.h>
+#include <mcld/MC/MCLDInput.h>
-namespace mcld
-{
+namespace mcld {
-class AttributeFactory;
+class LinkerConfig;
+class AttributeProxy;
+class AttributeSet;
/** \class InputFactory
* \brief InputFactory controls the production and destruction of
@@ -26,9 +27,6 @@
* All MCLDFiles created by MCLDFileFactory are guaranteed to be destructed
* while MCLDFileFactory is destructed.
*
- * FIXME: the number of the Inputs should be passed in by Target or any
- * target specific class.
- *
* \see llvm::sys::Path
*/
class InputFactory : public GCFactory<Input,0>
@@ -37,17 +35,24 @@
typedef GCFactory<Input, 0> Alloc;
public:
- InputFactory(size_t pNum, AttributeFactory& pAttrFactory);
+ InputFactory(size_t pNum, const LinkerConfig& pConfig);
+
~InputFactory();
- // ----- production ----- //
+ // ----- input ----- //
Input* produce(llvm::StringRef pName,
const sys::fs::Path& pPath,
unsigned int pType = Input::Unknown,
off_t pFileOffset = 0);
+ // ----- attributes ----- //
+ /// attr - the last touched attribute.
+ const AttributeProxy& attr() const { return *m_pLast; }
+ AttributeProxy& attr() { return *m_pLast; }
+
private:
- AttributeFactory &m_AttrFactory;
+ AttributeProxy* m_pLast;
+ AttributeSet* m_pAttrSet;
};
} // namespace of mcld
diff --git a/include/mcld/MC/MCFragmentRef.h b/include/mcld/MC/MCFragmentRef.h
deleted file mode 100644
index b7d94cd..0000000
--- a/include/mcld/MC/MCFragmentRef.h
+++ /dev/null
@@ -1,85 +0,0 @@
-//===- MCFragmentRef.h ----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_MCFRAGMENT_REFERENCE_H
-#define MCLD_MCFRAGMENT_REFERENCE_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <llvm/MC/MCAssembler.h>
-#include <mcld/ADT/SizeTraits.h>
-#include <mcld/ADT/TypeTraits.h>
-
-namespace mcld
-{
-
-class Layout;
-
-/// compunteFragmentSize - compute the specific MCFragment size
-uint64_t computeFragmentSize(const Layout& pLayout,
- const llvm::MCFragment& pFrag);
-
-/** \class MCFragmentRef
- * \brief MCFragmentRef is a reference of a MCFragment's contetnt.
- *
- */
-class MCFragmentRef
-{
-public:
- typedef uint64_t Offset; // FIXME: use SizeTraits<T>::Offset
- typedef NonConstTraits<unsigned char>::pointer Address;
- typedef ConstTraits<unsigned char>::pointer ConstAddress;
-
-public:
- MCFragmentRef();
- MCFragmentRef(llvm::MCFragment& pFrag, Offset pOffset = 0);
- ~MCFragmentRef();
-
- // ----- modifiers ----- //
- MCFragmentRef& assign(const MCFragmentRef& pCopy);
-
- MCFragmentRef& assign(llvm::MCFragment& pFrag, Offset pOffset = 0);
-
- /// memcpy - copy memory
- /// copy memory from the fragment to the pDesc.
- /// @pDest - the destination address
- /// @pNBytes - copies pNBytes from the fragment[offset()+pOffset]
- /// @pOffset - additional offset.
- /// the start address offset from fragment[offset()]
- void memcpy(void* pDest, size_t pNBytes, Offset pOffset = 0) const;
-
- // ----- observers ----- //
- llvm::MCFragment* frag()
- { return m_pFragment; }
-
- const llvm::MCFragment* frag() const
- { return m_pFragment; }
-
- Offset offset() const
- { return m_Offset; }
-
- // ----- dereference ----- //
- Address deref();
-
- ConstAddress deref() const;
-
- Address operator*()
- { return deref(); }
-
- ConstAddress operator*() const
- { return deref(); }
-
-private:
- llvm::MCFragment* m_pFragment;
- Offset m_Offset;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/MC/MCLDDriver.h b/include/mcld/MC/MCLDDriver.h
deleted file mode 100644
index 2259186..0000000
--- a/include/mcld/MC/MCLDDriver.h
+++ /dev/null
@@ -1,127 +0,0 @@
-//===- MCLDDriver.h --------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// MCLDDriver plays the same role as GNU collect2 to prepare all implicit
-// parameters for MCLinker.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MCLD_LDDRIVER_H
-#define MCLD_LDDRIVER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <mcld/LD/SectionMap.h>
-
-namespace mcld
-{
-
-class MCLinker;
-class MCLDInfo;
-class TargetLDBackend;
-class MemoryAreaFactory;
-
-/** \class MCLDDriver
- * \brief MCLDDriver prepares parameters for MCLinker.
- */
-class MCLDDriver
-{
-public:
- MCLDDriver(MCLDInfo& pLDInfo,
- TargetLDBackend& pLDBackend,
- MemoryAreaFactory& pAreaFactory);
-
- ~MCLDDriver();
-
- /// initMCLinker - initialize MCLinker
- /// Connect all components in MCLinker
- bool initMCLinker();
-
- /// initStdSections - initialize standard sections of the output file.
- bool initStdSections();
-
- /// normalize - normalize the input files
- void normalize();
-
- /// linkable - check the linkability of current MCLDInfo
- /// Check list:
- /// - check the Attributes are not violate the constaint
- /// - check every Input has a correct Attribute
- bool linkable() const;
-
- /// mergeSections - put allinput sections into output sections
- bool mergeSections();
-
- /// addStandardSymbols - shared object and executable files need some
- /// standard symbols
- /// @return if there are some input symbols with the same name to the
- /// standard symbols, return false
- bool addStandardSymbols();
-
- /// addTargetSymbols - some targets, such as MIPS and ARM, need some
- /// target-dependent symbols
- /// @return if there are some input symbols with the same name to the
- /// target symbols, return false
- bool addTargetSymbols();
-
- /// readRelocations - read all relocation entries
- bool readRelocations();
-
- /// prelayout - help backend to do some modification before layout
- bool prelayout();
-
- /// layout - linearly layout all output sections and reserve some space
- /// for GOT/PLT
- /// Because we do not support instruction relaxing in this early version,
- /// if there is a branch can not jump to its target, we return false
- /// directly
- bool layout();
-
- /// postlayout - help backend to do some modification after layout
- bool postlayout();
-
- /// relocate - applying relocation entries and create relocation
- /// section in the output files
- /// Create relocation section, asking TargetLDBackend to
- /// read the relocation information into RelocationEntry
- /// and push_back into the relocation section
- bool relocation();
-
- /// finalizeSymbolValue - finalize the symbol value
- bool finalizeSymbolValue();
-
- /// emitOutput - emit the output file.
- bool emitOutput();
-
- /// postProcessing - do modificatiion after all processes
- bool postProcessing();
-
- /// getLinker - get internal MCLinker object
- MCLinker* getLinker()
- { return m_pLinker; }
-
- /// getLinker - get internal MCLinker object
- const MCLinker* getLinker() const
- { return m_pLinker; }
-
- /// hasInitLinker - has Linker been initialized?
- bool hasInitLinker() const
- { return (NULL != m_pLinker); }
-
-private:
- MCLDInfo& m_LDInfo;
- TargetLDBackend &m_LDBackend;
- MCLinker* m_pLinker;
- SectionMap m_SectionMap;
- MemoryAreaFactory &m_AreaFactory;
-};
-
-} // end namespace mcld
-#endif
diff --git a/include/mcld/MC/MCLDFile.h b/include/mcld/MC/MCLDFile.h
deleted file mode 100644
index c780cb8..0000000
--- a/include/mcld/MC/MCLDFile.h
+++ /dev/null
@@ -1,174 +0,0 @@
-//===- MCLDFile.h ---------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// MCLDFile represents a file, the content of the file is stored in LDContext.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MCLD_LD_FILE_H
-#define MCLD_LD_FILE_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include "mcld/ADT/Uncopyable.h"
-#include "mcld/LD/LDContext.h"
-#include "mcld/Support/Path.h"
-#include "mcld/Support/FileSystem.h"
-#include "mcld/Support/GCFactory.h"
-#include "mcld/Support/MemoryArea.h"
-#include <llvm/ADT/StringRef.h>
-#include <string>
-#include <sys/stat.h>
-
-
-namespace mcld
-{
-class MemoryArea;
-
-/** \class MCLDFile
- * \brief MCLDFile represents the file being linked or produced.
- *
- * MCLDFile is the storage of name, path and type
- * A MCLDFile just refers to LDContext, not owns it.
- *
- * @see mcld::sys::fs::Path LDContext
- */
-class MCLDFile : private Uncopyable
-{
-public:
- enum Type {
- Unknown,
- Object,
- Exec,
- DynObj,
- CoreFile,
- Script,
- Archive,
- External
- };
-
-public:
- MCLDFile();
- MCLDFile(llvm::StringRef pName);
- MCLDFile(llvm::StringRef pName,
- const sys::fs::Path& pPath,
- unsigned int pType = Unknown);
-
- virtual ~MCLDFile();
-
- // ----- modifiers ----- //
- void setType(unsigned int pType)
- { m_Type = pType; }
-
- void setContext(LDContext* pContext)
- { m_pContext = pContext; }
-
- void setPath(const sys::fs::Path& pPath)
- { m_Path = pPath; }
-
- void setMemArea(MemoryArea* pMemArea)
- {
- m_pMemArea = pMemArea;
- }
-
- /// setSOName - set the name of the shared object.
- /// In ELF, this will be written in DT_SONAME
- void setSOName(const std::string& pName);
-
- // ----- observers ----- //
- unsigned int type() const
- { return m_Type; }
-
- const std::string& name() const
- { return m_Name; }
-
- const sys::fs::Path& path() const
- { return m_Path; }
-
- bool hasContext() const
- { return (0 != m_pContext); }
-
- LDContext* context()
- { return m_pContext; }
-
- const LDContext* context() const
- { return m_pContext; }
-
- bool hasMemArea() const
- { return (0 != m_pMemArea); }
-
- MemoryArea* memArea()
- { return m_pMemArea; }
-
- const MemoryArea* memArea() const
- { return m_pMemArea; }
-
-protected:
- unsigned int m_Type;
- LDContext *m_pContext;
- sys::fs::Path m_Path;
- std::string m_Name;
- MemoryArea* m_pMemArea;
-};
-
-/** \class MCLDFileFactory
- * \brief MCLDFileFactory controls the production and destruction of
- * MCLDFiles.
- *
- * All MCLDFiles created by MCLDFileFactory are guaranteed to be destructed
- * while MCLDFileFactory is destructed.
- *
- * MCLDFileFactory also provides the MCLCContextFactory to MCLDFile.
- * MCLDFile is responsed for the life of LDContext, therefore, the best
- * idea is let MCLDFile control the life of LDContext. Since SectLinker
- * has the need to count the number of LDContext, we give a central factory
- * for LDContext.
- *
- * \see llvm::sys::Path
- */
-template<size_t NUM>
-class MCLDFileFactory : public GCFactory<MCLDFile, NUM>
-{
-public:
- typedef GCFactory<MCLDFile, NUM> Alloc;
-
-public:
- // ----- production ----- //
- MCLDFile* produce(llvm::StringRef pName,
- const sys::fs::Path& pPath,
- unsigned int pType = MCLDFile::Unknown);
-
- MCLDFile* produce();
-};
-
-} // namespace of mcld
-
-//===----------------------------------------------------------------------===//
-// MCLDFileFactory
-template<size_t NUM>
-mcld::MCLDFile* mcld::MCLDFileFactory<NUM>::produce(llvm::StringRef pName,
- const mcld::sys::fs::Path& pPath,
- unsigned int pType)
-{
- mcld::MCLDFile* result = Alloc::allocate();
- new (result) mcld::MCLDFile(pName, pPath, pType);
- return result;
-}
-
-template<size_t NUM>
-mcld::MCLDFile* mcld::MCLDFileFactory<NUM>::produce()
-{
- mcld::MCLDFile* result = Alloc::allocate();
- new (result) mcld::MCLDFile();
- return result;
-}
-
-#endif
-
diff --git a/include/mcld/MC/MCLDInfo.h b/include/mcld/MC/MCLDInfo.h
deleted file mode 100644
index d76fff4..0000000
--- a/include/mcld/MC/MCLDInfo.h
+++ /dev/null
@@ -1,137 +0,0 @@
-//===- MCLDInfo.h ---------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_LDINFO_H
-#define MCLD_LDINFO_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <llvm/ADT/Triple.h>
-
-#include <mcld/Support/FileSystem.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLDOptions.h>
-#include <mcld/MC/InputTree.h>
-#include <mcld/MC/AttributeFactory.h>
-#include <mcld/MC/ContextFactory.h>
-#include <mcld/LD/NamePool.h>
-
-#include <string>
-#include <cassert>
-
-namespace mcld
-{
-class Resolver;
-
-/** \class MCLDInfo
- * \brief MCLDInfo is composed of argumments of MCLinker.
- * options() - the general options
- * scripts() - the script options
- * inputs() - the tree of inputs
- * bitcode() - the bitcode being linked
- * output() - the output file
- * inputFactory() - the list of all inputs
- * attrFactory() - the list of all attributes
- * contextFactory() - the list of all contexts.
- * memAreaFactory() - the list of all MemoryAreas.
- */
-class MCLDInfo
-{
-public:
- explicit MCLDInfo(const std::string &pTripleString,
- size_t pAttrNum,
- size_t InputSize);
-
- virtual ~MCLDInfo();
-
- GeneralOptions& options()
- { return m_Options; }
-
- const GeneralOptions& options() const
- { return m_Options; }
-
- ScriptOptions& scripts()
- { return m_Scripts; }
-
- const ScriptOptions& scripts() const
- { return m_Scripts; }
-
- void setBitcode(const Input& pInput);
- Input& bitcode();
- const Input& bitcode() const;
-
- Output& output()
- { return *m_pOutput; }
-
- const Output& output() const
- { return *m_pOutput; }
-
- InputTree& inputs()
- { return *m_pInputTree; }
-
- const InputTree& inputs() const
- { return *m_pInputTree; }
-
- InputFactory& inputFactory()
- { return *m_pInputFactory; }
-
- const InputFactory& inputFactory() const
- { return *m_pInputFactory; }
-
- AttributeFactory& attrFactory()
- { return *m_pAttrFactory; }
-
-
- const AttributeFactory& attrFactory() const
- { return *m_pAttrFactory; }
-
- ContextFactory& contextFactory()
- { return *m_pCntxtFactory; }
-
- const ContextFactory& contextFactory() const
- { return *m_pCntxtFactory; }
-
- const llvm::Triple& triple() const
- { return m_Triple; }
-
- static const char* version();
-
- NamePool& getNamePool() {
- assert(NULL != m_pNamePool);
- return *m_pNamePool;
- }
-
- const NamePool& getNamePool() const {
- assert(NULL != m_pNamePool);
- return *m_pNamePool;
- }
-
-private:
- // ----- General Options ----- //
- GeneralOptions m_Options;
- ScriptOptions m_Scripts;
- InputTree *m_pInputTree;
- Input* m_pBitcode;
- Output* m_pOutput;
- llvm::Triple m_Triple;
-
- // ----- factories ----- //
- InputFactory *m_pInputFactory;
- AttributeFactory *m_pAttrFactory;
- ContextFactory *m_pCntxtFactory;
-
- // ----- string and symbols ----- //
- Resolver* m_pResolver;
- NamePool* m_pNamePool;
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/MC/MCLDInput.h b/include/mcld/MC/MCLDInput.h
index e9bb4e6..94b9479 100644
--- a/include/mcld/MC/MCLDInput.h
+++ b/include/mcld/MC/MCLDInput.h
@@ -10,43 +10,50 @@
// Input class inherits MCLDFile, which is used to represent a input file
//
//===----------------------------------------------------------------------===//
-
#ifndef MCLD_INPUT_H
#define MCLD_INPUT_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include "mcld/MC/MCLDFile.h"
+#include <mcld/Support/Path.h>
-namespace mcld
-{
+namespace mcld {
+class MemoryArea;
class AttributeProxy;
class Attribute;
class InputFactory;
+class LDContext;
/** \class Input
* \brief Input provides the information of a input file.
- *
- * @see MCLDFile
*/
-class Input : public MCLDFile
+class Input
{
friend class InputFactory;
public:
enum Type {
- Unknown = MCLDFile::Unknown,
- Object = MCLDFile::Object,
- DynObj = MCLDFile::DynObj,
- Archive = MCLDFile::Archive,
- Script = MCLDFile::Script,
- External = MCLDFile::External
+ Unknown,
+ Object,
+ Exec,
+ DynObj,
+ CoreFile,
+ Script,
+ Archive,
+ External
};
-private:
- explicit Input(llvm::StringRef pName,
- const AttributeProxy& pAttr);
+public:
+ explicit Input(llvm::StringRef pName);
+
+ Input(llvm::StringRef pName,
+ const AttributeProxy& pAttr);
+
+ Input(llvm::StringRef pName,
+ const sys::fs::Path& pPath,
+ unsigned int pType = Unknown,
+ off_t pFileOffset = 0);
Input(llvm::StringRef pName,
const sys::fs::Path& pPath,
@@ -54,12 +61,32 @@
unsigned int pType = Unknown,
off_t pFileOffset = 0);
-public:
~Input();
+ const std::string& name() const
+ { return m_Name; }
+
+ void setName(const std::string& pName)
+ { m_Name = pName; }
+
+ const sys::fs::Path& path() const
+ { return m_Path; }
+
+ void setPath(const sys::fs::Path& pPath)
+ { m_Path = pPath; }
+
+ void setType(unsigned int pType)
+ { m_Type = pType; }
+
+ unsigned int type() const
+ { return m_Type; }
+
bool isRecognized() const
{ return (m_Type != Unknown); }
+ bool hasAttribute() const
+ { return (NULL != m_pAttr); }
+
const Attribute* attribute() const
{ return m_pAttr; }
@@ -75,10 +102,35 @@
void setFileOffset(off_t pFileOffset)
{ m_fileOffset = pFileOffset; }
+ // ----- memory area ----- //
+ void setMemArea(MemoryArea* pMemArea)
+ { m_pMemArea = pMemArea; }
+
+ bool hasMemArea() const
+ { return (NULL != m_pMemArea); }
+
+ const MemoryArea* memArea() const { return m_pMemArea; }
+ MemoryArea* memArea() { return m_pMemArea; }
+
+ // ----- context ----- //
+ void setContext(LDContext* pContext)
+ { m_pContext = pContext; }
+
+ bool hasContext() const
+ { return (NULL != m_pContext); }
+
+ const LDContext* context() const { return m_pContext; }
+ LDContext* context() { return m_pContext; }
+
private:
+ unsigned int m_Type;
+ std::string m_Name;
+ sys::fs::Path m_Path;
Attribute *m_pAttr;
bool m_bNeeded;
off_t m_fileOffset;
+ MemoryArea* m_pMemArea;
+ LDContext* m_pContext;
};
} // namespace of mcld
diff --git a/include/mcld/MC/MCLDOutput.h b/include/mcld/MC/MCLDOutput.h
deleted file mode 100644
index 14768ce..0000000
--- a/include/mcld/MC/MCLDOutput.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- MCLDOutput.h -------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Output class inherits MCLDFile, which is used to represent a output file.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MCLD_OUTPUT_H
-#define MCLD_OUTPUT_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <mcld/MC/MCLDFile.h>
-#include <mcld/Support/RealPath.h>
-#include <string>
-
-namespace mcld
-{
-
-/** \class MCLDOutput
- * \brief MCLDOutput provides the information about the output.
- *
- * @see MCLDFile
- */
-class Output : public MCLDFile
-{
-public:
- enum Type {
- Object = MCLDFile::Object,
- DynObj = MCLDFile::DynObj,
- Exec = MCLDFile::Exec
- };
-
-public:
- Output();
- explicit Output(const sys::fs::Path& pRealPath,
- Type pType);
-
- ~Output();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/MC/SearchDirs.h b/include/mcld/MC/SearchDirs.h
index e0cf169..13cc12f 100644
--- a/include/mcld/MC/SearchDirs.h
+++ b/include/mcld/MC/SearchDirs.h
@@ -6,27 +6,25 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef SEARCHDIRS_H
-#define SEARCHDIRS_H
+#ifndef MCLD_MC_SEARCHDIRS_H
+#define MCLD_MC_SEARCHDIRS_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <llvm/ADT/StringRef.h>
-#include "mcld/ADT/Uncopyable.h"
-#include "mcld/MC/MCLDInput.h"
+#include <mcld/ADT/Uncopyable.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/Support/Path.h>
-namespace mcld
-{
+#include <llvm/ADT/StringRef.h>
+
+#include <vector>
+#include <string>
+
+namespace mcld {
class MCLDFile;
class MCLDDirectory;
-namespace sys {
-namespace fs {
-class Path;
-} // namespace of fs
-} // namespace of sys
-
/** \class SearchDirs
* \brief SearchDirs contains the list of paths that MCLinker will search for
* archive libraries and control scripts.
@@ -45,30 +43,35 @@
public:
SearchDirs();
+
+ SearchDirs(const sys::fs::Path& pSysRoot);
+
~SearchDirs();
// find - give a namespec, return a real path of the shared object.
- //
- sys::fs::Path* find(const std::string& pNamespec, mcld::Input::Type pPreferType);
+ sys::fs::Path*
+ find(const std::string& pNamespec, mcld::Input::Type pPreferType);
+
+ const sys::fs::Path*
+ find(const std::string& pNamespec, mcld::Input::Type pPreferType) const;
+
+ void setSysRoot(const sys::fs::Path& pSysRoot) { m_SysRoot = pSysRoot; }
+ const sys::fs::Path& sysroot() const { return m_SysRoot; }
// ----- iterators ----- //
- iterator begin()
- { return m_DirList.begin(); }
-
- iterator end()
- { return m_DirList.end(); }
-
- const_iterator begin() const
- { return m_DirList.begin(); }
-
- const_iterator end() const
- { return m_DirList.end(); }
+ const_iterator begin() const { return m_DirList.begin(); }
+ iterator begin() { return m_DirList.begin(); }
+ const_iterator end () const { return m_DirList.end(); }
+ iterator end () { return m_DirList.end(); }
// ----- modifiers ----- //
- void add(const MCLDDirectory& pDirectory);
+ bool insert(const std::string& pDirectory);
+
+ bool insert(const sys::fs::Path& pDirectory);
private:
DirList m_DirList;
+ sys::fs::Path m_SysRoot;
};
} // namespace of mcld
diff --git a/include/mcld/MC/SymbolCategory.h b/include/mcld/MC/SymbolCategory.h
index 9432c2a..3aa16c5 100644
--- a/include/mcld/MC/SymbolCategory.h
+++ b/include/mcld/MC/SymbolCategory.h
@@ -45,6 +45,8 @@
SymbolCategory& changeCommonsToGlobal();
+ SymbolCategory& changeLocalToTLS(const LDSymbol& pSymbol);
+
// ----- access ----- //
LDSymbol& at(size_t pPosition)
{ return *m_OutputSymbols.at(pPosition); }
@@ -70,7 +72,7 @@
bool empty() const;
bool emptyLocals() const;
-
+
bool emptyCommons() const;
bool emptyRegulars() const;
@@ -86,6 +88,11 @@
const_iterator localBegin() const;
const_iterator localEnd() const;
+ iterator tlsBegin();
+ iterator tlsEnd();
+ const_iterator tlsBegin() const;
+ const_iterator tlsEnd() const;
+
iterator commonBegin();
iterator commonEnd();
const_iterator commonBegin() const;
@@ -103,6 +110,7 @@
enum Type {
File,
Local,
+ TLS,
Common,
Weak,
Global
@@ -147,6 +155,7 @@
Category* m_pFile;
Category* m_pLocal;
+ Category* m_pTLS;
Category* m_pCommon;
Category* m_pWeak;
Category* m_pGlobal;
diff --git a/include/mcld/Module.h b/include/mcld/Module.h
new file mode 100644
index 0000000..36dda97
--- /dev/null
+++ b/include/mcld/Module.h
@@ -0,0 +1,166 @@
+//===- Module.h -----------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Module contains the intermediate representation (LDIR) of MCLinker.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_MODULE_H
+#define MCLD_MODULE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <vector>
+#include <string>
+
+#include <llvm/ADT/ilist.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>
+
+namespace mcld {
+
+class LDSection;
+class LDSymbol;
+
+/** \class Module
+ * \brief Module provides the intermediate representation for linking.
+ */
+class Module
+{
+public:
+ typedef std::vector<Input*> ObjectList;
+ typedef ObjectList::iterator obj_iterator;
+ typedef ObjectList::const_iterator const_obj_iterator;
+
+ typedef std::vector<Input*> LibraryList;
+ typedef LibraryList::iterator lib_iterator;
+ typedef LibraryList::const_iterator const_lib_iterator;
+
+ typedef InputTree::iterator input_iterator;
+ typedef InputTree::const_iterator const_input_iterator;
+
+ typedef std::vector<LDSection*> SectionTable;
+ typedef SectionTable::iterator iterator;
+ typedef SectionTable::const_iterator const_iterator;
+
+ typedef SymbolCategory SymbolTable;
+ typedef SymbolTable::iterator sym_iterator;
+ typedef SymbolTable::const_iterator const_sym_iterator;
+
+public:
+ Module();
+
+ Module(const std::string& pName);
+
+ ~Module();
+
+ // ----- name ----- //
+ const std::string& name() const { return m_Name; }
+
+ void setName(const std::string& pName) { m_Name = pName; }
+
+ // ----- link-in objects ----- //
+ const ObjectList& getObjectList() const { return m_ObjectList; }
+ ObjectList& getObjectList() { return m_ObjectList; }
+
+ const_obj_iterator obj_begin() const { return m_ObjectList.begin(); }
+ obj_iterator obj_begin() { return m_ObjectList.begin(); }
+ const_obj_iterator obj_end () const { return m_ObjectList.end(); }
+ obj_iterator obj_end () { return m_ObjectList.end(); }
+
+ // ----- link-in libraries ----- //
+ const LibraryList& getLibraryList() const { return m_LibraryList; }
+ LibraryList& getLibraryList() { return m_LibraryList; }
+
+ const_lib_iterator lib_begin() const { return m_LibraryList.begin(); }
+ lib_iterator lib_begin() { return m_LibraryList.begin(); }
+ const_lib_iterator lib_end () const { return m_LibraryList.end(); }
+ lib_iterator lib_end () { return m_LibraryList.end(); }
+
+ // ----- link-in inputs ----- //
+ const InputTree& getInputTree() const { return m_MainTree; }
+ InputTree& getInputTree() { return m_MainTree; }
+
+ const_input_iterator input_begin() const { return m_MainTree.begin(); }
+ input_iterator input_begin() { return m_MainTree.begin(); }
+ const_input_iterator input_end () const { return m_MainTree.end(); }
+ input_iterator input_end () { return m_MainTree.end(); }
+
+/// @}
+/// @name Section Accessors
+/// @{
+
+ // ----- sections ----- //
+ const SectionTable& getSectionTable() const { return m_SectionTable; }
+ SectionTable& getSectionTable() { return m_SectionTable; }
+
+ iterator begin() { return m_SectionTable.begin(); }
+ const_iterator begin() const { return m_SectionTable.begin(); }
+ iterator end () { return m_SectionTable.end(); }
+ const_iterator end () const { return m_SectionTable.end(); }
+ LDSection* front() { return m_SectionTable.front(); }
+ const LDSection* front() const { return m_SectionTable.front(); }
+ LDSection* back () { return m_SectionTable.back(); }
+ const LDSection* back () const { return m_SectionTable.back(); }
+ size_t size () const { return m_SectionTable.size(); }
+ bool empty() const { return m_SectionTable.empty(); }
+
+ LDSection* getSection(const std::string& pName);
+ const LDSection* getSection(const std::string& pName) const;
+
+ LDSymbol* getSectionSymbol(const LDSection* pSection);
+ const LDSymbol* getSectionSymbol(const LDSection* pSection) const;
+
+/// @}
+/// @name Symbol Accessors
+/// @{
+
+ // ----- symbols ----- //
+ const SymbolTable& getSymbolTable() const { return m_SymbolTable; }
+ SymbolTable& getSymbolTable() { return m_SymbolTable; }
+
+ sym_iterator sym_begin() { return m_SymbolTable.begin(); }
+ const_sym_iterator sym_begin() const { return m_SymbolTable.begin(); }
+ sym_iterator sym_end () { return m_SymbolTable.end(); }
+ const_sym_iterator sym_end () const { return m_SymbolTable.end(); }
+ size_t sym_size () const { return m_SymbolTable.numOfSymbols(); }
+
+ // ----- section symbols ----- //
+ const SectionSymbolSet& getSectionSymbolSet() const
+ { return m_SectSymbolSet; }
+ SectionSymbolSet& getSectionSymbolSet()
+ { return m_SectSymbolSet; }
+
+ // ----- names ----- //
+ const NamePool& getNamePool() const { return m_NamePool; }
+ NamePool& getNamePool() { return m_NamePool; }
+
+private:
+ std::string m_Name;
+ ObjectList m_ObjectList;
+ LibraryList m_LibraryList;
+ InputTree m_MainTree;
+ SectionTable m_SectionTable;
+ SymbolTable m_SymbolTable;
+ NamePool m_NamePool;
+ SectionSymbolSet m_SectSymbolSet;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Object/ObjectBuilder.h b/include/mcld/Object/ObjectBuilder.h
new file mode 100644
index 0000000..bfa4c6b
--- /dev/null
+++ b/include/mcld/Object/ObjectBuilder.h
@@ -0,0 +1,99 @@
+//===- ObjectBuilder.h ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_OBJECT_OBJECT_BUILDER_H
+#define MCLD_OBJECT_OBJECT_BUILDER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/LD/LDFileFormat.h>
+#include <mcld/LD/EhFrame.h>
+
+#include <llvm/Support/DataTypes.h>
+
+#include <string>
+
+namespace mcld {
+
+class LinkerConfig;
+class Module;
+class LDSection;
+class SectionData;
+class RelocData;
+class Fragment;
+class Relocation;
+
+/** \class ObjectBuilder
+ * \brief ObjectBuilder recieve ObjectAction and build the mcld::Module.
+ */
+class ObjectBuilder
+{
+public:
+ ObjectBuilder(const LinkerConfig& pConfig,
+ Module& pTheModule);
+
+/// @}
+/// @name Section Methods
+/// @{
+ /// CreateSection - To create an output LDSection in mcld::Module.
+ /// Link scripts and command line options define some SECTIONS commands that
+ /// specify where input sections are placed into output sections. This function
+ /// checks SECTIONS commands to change given name to the output section name.
+ /// This function creates a new LDSection and push the created LDSection into
+ /// @ref mcld::Module.
+ ///
+ /// To create an input LDSection in mcld::LDContext, use @ref LDSection::Create().
+ ///
+ /// @see SectionMap
+ ///
+ /// @param [in] pName The given name. Returned LDSection used the changed name
+ /// by SectionMap.
+ LDSection* CreateSection(const std::string& pInputName,
+ LDFileFormat::Kind pKind,
+ uint32_t pType,
+ uint32_t pFlag,
+ uint32_t pAlign = 0x0);
+
+ /// MergeSection - merge the pInput section to mcld::Module.
+ /// This function moves all fragments in pInputSection to the corresponding
+ /// output section of mcld::Module.
+ ///
+ /// @see SectionMap
+ /// @param [in] pInputSection The merged input section.
+ /// @return If the corresponding output sections is not defined, return false.
+ bool MergeSection(LDSection& pInputSection);
+
+ /// MoveSectionData - move the fragment of pFrom to pTo section data.
+ static bool MoveSectionData(SectionData& pFrom, SectionData& pTo);
+
+/// @}
+/// @name Fragment Methods
+/// @{
+ /// AppendFragment - To append pFrag to the given SectionData pSD.
+ /// In order to keep the alignment of pFrag, This function inserts an
+ /// AlignFragment before pFrag if pAlignConstraint is larger than 1.
+ ///
+ /// @note This function does not update the alignment constraint of LDSection.
+ ///
+ /// @param [in, out] pFrag The appended fragment. The offset of the appended
+ /// pFrag is set to the offset in pSD.
+ /// @param [in, out] pSD The section data being appended.
+ /// @param [in] pAlignConstraint The alignment constraint.
+ /// @return Total size of the inserted fragments.
+ static uint64_t AppendFragment(Fragment& pFrag, SectionData& pSD,
+ uint32_t pAlignConstraint = 1);
+
+private:
+ const LinkerConfig& m_Config;
+ Module& m_Module;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Object/ObjectLinker.h b/include/mcld/Object/ObjectLinker.h
new file mode 100644
index 0000000..4d9f642
--- /dev/null
+++ b/include/mcld/Object/ObjectLinker.h
@@ -0,0 +1,168 @@
+//===- ObjectLinker.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// 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
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <stddef.h>
+
+namespace mcld {
+
+class Module;
+class LinkerConfig;
+class InputBuilder;
+class FragmentLinker;
+class TargetLDBackend;
+class MemoryArea;
+class MemoryAreaFactory;
+class ObjectReader;
+class DynObjReader;
+class ArchiveReader;
+class GroupReader;
+class ObjectWriter;
+class DynObjWriter;
+class ExecWriter;
+
+/** \class ObjectLinker
+ * \brief ObjectLinker prepares parameters for FragmentLinker.
+ */
+class ObjectLinker
+{
+public:
+ ObjectLinker(const LinkerConfig& pConfig,
+ Module& pModule,
+ InputBuilder& pInputBuilder,
+ TargetLDBackend& pLDBackend);
+
+ ~ObjectLinker();
+
+ /// initFragmentLinker - initialize FragmentLinker
+ /// Connect all components in FragmentLinker
+ bool initFragmentLinker();
+
+ /// initStdSections - initialize standard sections of the output file.
+ bool initStdSections();
+
+ /// normalize - normalize the input files
+ void normalize();
+
+ /// linkable - check the linkability of current LinkerConfig
+ /// Check list:
+ /// - check the Attributes are not violate the constaint
+ /// - check every Input has a correct Attribute
+ bool linkable() const;
+
+ /// readRelocations - read all relocation entries
+ bool readRelocations();
+
+ /// mergeSections - put allinput sections into output sections
+ bool mergeSections();
+
+ /// addStandardSymbols - shared object and executable files need some
+ /// standard symbols
+ /// @return if there are some input symbols with the same name to the
+ /// standard symbols, return false
+ bool addStandardSymbols();
+
+ /// addTargetSymbols - some targets, such as MIPS and ARM, need some
+ /// target-dependent symbols
+ /// @return if there are some input symbols with the same name to the
+ /// target symbols, return false
+ bool addTargetSymbols();
+
+ /// scanRelocations - scan all relocation entries by output symbols.
+ bool scanRelocations();
+
+ /// prelayout - help backend to do some modification before layout
+ bool prelayout();
+
+ /// layout - linearly layout all output sections and reserve some space
+ /// for GOT/PLT
+ /// Because we do not support instruction relaxing in this early version,
+ /// if there is a branch can not jump to its target, we return false
+ /// directly
+ bool layout();
+
+ /// postlayout - help backend to do some modification after layout
+ bool postlayout();
+
+ /// relocate - applying relocation entries and create relocation
+ /// section in the output files
+ /// Create relocation section, asking TargetLDBackend to
+ /// read the relocation information into RelocationEntry
+ /// and push_back into the relocation section
+ bool relocation();
+
+ /// finalizeSymbolValue - finalize the symbol value
+ bool finalizeSymbolValue();
+
+ /// emitOutput - emit the output file.
+ bool emitOutput(MemoryArea& 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); }
+
+ // ----- readers and writers ----- //
+ const ObjectReader* getObjectReader () const { return m_pObjectReader; }
+ ObjectReader* getObjectReader () { return m_pObjectReader; }
+
+ const DynObjReader* getDynObjReader () const { return m_pDynObjReader; }
+ DynObjReader* getDynObjReader () { return m_pDynObjReader; }
+
+ const ArchiveReader* getArchiveReader() const { return m_pArchiveReader; }
+ ArchiveReader* getArchiveReader() { return m_pArchiveReader; }
+
+ const GroupReader* getGroupReader() const { return m_pGroupReader; }
+ GroupReader* getGroupReader() { return m_pGroupReader; }
+
+ const ObjectWriter* getObjectWriter () const { return m_pObjectWriter; }
+ ObjectWriter* getObjectWriter () { return m_pObjectWriter; }
+
+ const DynObjWriter* getDynObjWriter () const { return m_pDynObjWriter; }
+ DynObjWriter* getDynObjWriter () { return m_pDynObjWriter; }
+
+ const ExecWriter* getExecWriter () const { return m_pExecWriter; }
+ ExecWriter* getExecWriter () { return m_pExecWriter; }
+
+private:
+ const LinkerConfig& m_Config;
+ Module& m_Module;
+
+ // we pass in InputBuilder for Archive and GroupReader.
+ InputBuilder& m_InputBuilder;
+
+ FragmentLinker* m_pLinker;
+ TargetLDBackend &m_LDBackend;
+
+ // ----- readers and writers ----- //
+ ObjectReader* m_pObjectReader;
+ DynObjReader* m_pDynObjReader;
+ ArchiveReader* m_pArchiveReader;
+ ObjectWriter* m_pObjectWriter;
+ DynObjWriter* m_pDynObjWriter;
+ ExecWriter* m_pExecWriter;
+ GroupReader* m_pGroupReader;
+};
+
+} // end namespace mcld
+#endif
diff --git a/include/mcld/Object/SectionMap.h b/include/mcld/Object/SectionMap.h
new file mode 100644
index 0000000..37df4a3
--- /dev/null
+++ b/include/mcld/Object/SectionMap.h
@@ -0,0 +1,90 @@
+//===- SectionMap.h -------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SECTION_MAP_H
+#define MCLD_SECTION_MAP_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <vector>
+#include <string>
+
+#include <llvm/Support/DataTypes.h>
+
+namespace mcld {
+
+/** \class SectionMap
+ * \brief descirbe the mappings of input section's name (or prefix) to
+ * its associated output section's name and offset
+ */
+class SectionMap
+{
+public:
+ // a mapping in SectionMap is the triple of
+ // {input substr, output section's name, output section's offset}
+ struct NamePair
+ {
+ public:
+ NamePair();
+ NamePair(const std::string& pFrom, const std::string& pTo);
+
+ bool isNull() const;
+
+ public:
+ unsigned int hash;
+ std::string from;
+ std::string to;
+ };
+
+ typedef std::vector<NamePair> NamePairList;
+ typedef NamePairList::iterator iterator;
+ typedef NamePairList::const_iterator const_iterator;
+
+ /// NullName - the null object of NamePair
+ static NamePair NullName;
+
+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);
+
+ const NamePair& find(const std::string& pFrom, unsigned int pHash) const;
+ NamePair& find(const std::string& pFrom, unsigned int pHash);
+
+ // 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 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(); }
+
+ bool empty() const { return m_NamePairList.empty(); }
+ size_t size () const { return m_NamePairList.size(); }
+
+ static unsigned int hash(const std::string& pString);
+
+private:
+ bool matched(const NamePair& pNamePair,
+ const std::string& pInput,
+ unsigned int pHash) const;
+private:
+ NamePairList m_NamePairList;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/ScriptOptions.h b/include/mcld/ScriptOptions.h
new file mode 100644
index 0000000..e240169
--- /dev/null
+++ b/include/mcld/ScriptOptions.h
@@ -0,0 +1,60 @@
+//===- ScriptOptions.h ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SCRIPT_OPTIONS_H
+#define MCLD_SCRIPT_OPTIONS_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <string>
+#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>
+
+namespace mcld {
+
+/** \class ScriptOptions
+ *
+ */
+class ScriptOptions
+{
+public:
+ typedef HashTable<StringEntry<llvm::StringRef>,
+ StringHash<ELF>,
+ StringEntryFactory<llvm::StringRef> > SymbolRenameMap;
+
+ typedef HashTable<StringEntry<uint64_t>,
+ StringHash<ELF>,
+ StringEntryFactory<uint64_t> > AddressMap;
+
+public:
+ ScriptOptions();
+
+ ~ScriptOptions();
+
+ const SymbolRenameMap& renameMap() const { return m_SymbolRenames; }
+ SymbolRenameMap& renameMap() { return m_SymbolRenames; }
+
+ const AddressMap& addressMap() const { return m_AddressMap; }
+ AddressMap& addressMap() { return m_AddressMap; }
+
+ const SectionMap& sectionMap() const { return m_SectionMap; }
+ SectionMap& sectionMap() { return m_SectionMap; }
+
+private:
+ SymbolRenameMap m_SymbolRenames;
+ AddressMap m_AddressMap;
+ SectionMap m_SectionMap;
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Support/Allocators.h b/include/mcld/Support/Allocators.h
index de6edec..e651093 100644
--- a/include/mcld/Support/Allocators.h
+++ b/include/mcld/Support/Allocators.h
@@ -6,20 +6,18 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ALLOCATORS_H
-#define LLVM_ALLOCATORS_H
+#ifndef MCLD_SUPPORT_ALLOCATORS_H
+#define MCLD_SUPPORT_ALLOCATORS_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include "mcld/ADT/Uncopyable.h"
-#include "mcld/ADT/TypeTraits.h"
-#include "mcld/LD/LDContext.h"
+#include <mcld/ADT/Uncopyable.h>
+#include <mcld/ADT/TypeTraits.h>
+
#include <cstddef>
#include <cstdlib>
-namespace mcld
-{
+namespace mcld {
/** \class Chunk
* \brief Chunk is the basic unit of the storage of the LinearAllocator
@@ -27,7 +25,7 @@
* @see LinearAllocator
*/
template<typename DataType, size_t ChunkSize>
-struct Chunk
+class Chunk
{
public:
typedef DataType value_type;
@@ -38,6 +36,15 @@
static size_t size() { return ChunkSize; }
+ static void construct(value_type* pPtr)
+ { new (pPtr) value_type(); }
+
+ static void construct(value_type* pPtr, const value_type& pValue)
+ { new (pPtr) value_type(pValue); }
+
+ static void destroy(value_type* pPtr)
+ { }
+
public:
Chunk* next;
size_t bound;
@@ -45,7 +52,7 @@
};
template<typename DataType>
-struct Chunk<DataType, 0>
+class Chunk<DataType, 0>
{
public:
typedef DataType value_type;
@@ -64,9 +71,19 @@
free(data);
}
- static size_t size() { return m_Size; }
+ static size_t size() { return m_Size; }
+
static void setSize(size_t pSize) { m_Size = pSize; }
+ static void construct(value_type* pPtr)
+ { new (pPtr) value_type(); }
+
+ static void construct(value_type* pPtr, const value_type& pValue)
+ { new (pPtr) value_type(pValue); }
+
+ static void destroy(value_type* pPtr)
+ { pPtr->~value_type(); }
+
public:
Chunk* next;
size_t bound;
@@ -117,7 +134,7 @@
// @param pPtr the address where the object to be constructed
// @param pValue the value to be constructed
void construct(pointer pPtr, const_reference pValue)
- { new (pPtr) value_type(pValue); }
+ { chunk_type::construct(pPtr, pValue); }
/// default construct - constructing an object on the location pointed by
// pPtr, and using its default constructor to initialized its value to
@@ -125,12 +142,12 @@
//
// @param pPtr the address where the object to be constructed
void construct(pointer pPtr)
- { new (pPtr) value_type(); }
+ { chunk_type::construct(pPtr); }
/// standard destroy - destroy data on arbitrary address
// @para pPtr the address where the data to be destruected.
void destroy(pointer pPtr)
- { pPtr->~value_type(); }
+ { chunk_type::destroy(pPtr); }
/// allocate - allocate N data in order.
// - Disallow to allocate a chunk whose size is bigger than a chunk.
@@ -147,8 +164,8 @@
size_type rest_num_elem = chunk_type::size() - m_pCurrent->bound;
pointer result = 0;
if (N > rest_num_elem)
- createChunk();
- result = const_cast<pointer>(&(m_pCurrent->data[m_pCurrent->bound]));
+ getNewChunk();
+ result = m_pCurrent->data + m_pCurrent->bound;
m_pCurrent->bound += N;
return result;
}
@@ -160,8 +177,8 @@
pointer result = 0;
if (chunk_type::size() == m_pCurrent->bound)
- createChunk();
- result = const_cast<pointer>(&(m_pCurrent->data[m_pCurrent->bound]));
+ getNewChunk();
+ result = m_pCurrent->data + m_pCurrent->bound;
++m_pCurrent->bound;
return result;
}
@@ -217,13 +234,10 @@
void clear() {
chunk_type *cur = m_pRoot, *prev;
while (0 != cur) {
- unsigned int idx=0;
prev = cur;
cur = cur->next;
- while (idx != prev->bound) {
- destroy(&prev->data[idx]);
- ++idx;
- }
+ for (unsigned int idx = 0; idx != prev->bound; ++idx)
+ destroy(prev->data + idx);
delete prev;
}
reset();
@@ -244,7 +258,7 @@
m_AllocatedNum += chunk_type::size();
}
- inline chunk_type *createChunk() {
+ inline chunk_type *getNewChunk() {
chunk_type *result = new chunk_type();
m_pCurrent->next = result;
m_pCurrent = result;
diff --git a/include/mcld/Support/DerivedPositionDependentOptions.h b/include/mcld/Support/DerivedPositionDependentOptions.h
deleted file mode 100644
index 2254a5f..0000000
--- a/include/mcld/Support/DerivedPositionDependentOptions.h
+++ /dev/null
@@ -1,137 +0,0 @@
-//===- DerivedPositionDependentOptions.h ----------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_DERIVEDPOSITIONDEPENDENTOPTIONS_H
-#define MCLD_DERIVEDPOSITIONDEPENDENTOPTIONS_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <string>
-
-#include "mcld/Support/RealPath.h"
-#include "mcld/Support/PositionDependentOption.h"
-
-namespace mcld
-{
-
- /** \class DerivedPositionDependentOptions
- * \brief This file contains the declarations of classes derived from PositionDependentOption.
- */
-
- class FileOption : public PositionDependentOption {
- private:
- sys::fs::RealPath m_Path;
-
- protected:
- FileOption(unsigned pPosition, Type pType, const sys::fs::Path &pPath)
- : PositionDependentOption(pPosition, pType)
- { m_Path.assign(pPath); }
-
- public:
- inline const sys::fs::Path *path() const { return &m_Path; }
- };
-
- class NamespecOption : public PositionDependentOption {
- private:
- std::string m_pNamespec;
-
- public:
- NamespecOption(unsigned pPosition, const std::string &pNamespec)
- : PositionDependentOption(pPosition, PositionDependentOption::NAMESPEC),
- m_pNamespec(pNamespec) { }
-
- inline const std::string &namespec() const { return m_pNamespec; }
- };
-
- class BitcodeOption : public FileOption {
- public:
- BitcodeOption(unsigned pPosition, const sys::fs::Path &pPath)
- : FileOption(pPosition, PositionDependentOption::BITCODE, pPath) { }
- };
-
- class StartGroupOption : public PositionDependentOption {
- public:
- StartGroupOption(unsigned pPosition)
- : PositionDependentOption(pPosition,
- PositionDependentOption::START_GROUP) { }
- };
-
- class EndGroupOption : public PositionDependentOption {
- public:
- EndGroupOption(unsigned pPosition)
- : PositionDependentOption(pPosition,
- PositionDependentOption::END_GROUP) { }
- };
-
- class InputFileOption : public FileOption {
- public:
- InputFileOption(unsigned pPosition, const sys::fs::Path &pPath)
- : FileOption(pPosition, PositionDependentOption::INPUT_FILE, pPath) { }
- };
-
- class WholeArchiveOption : public PositionDependentOption {
- public:
- WholeArchiveOption(unsigned pPosition)
- : PositionDependentOption(pPosition,
- PositionDependentOption::WHOLE_ARCHIVE) { }
- };
-
- class NoWholeArchiveOption : public PositionDependentOption {
- public:
- NoWholeArchiveOption(unsigned pPosition)
- : PositionDependentOption(pPosition,
- PositionDependentOption::NO_WHOLE_ARCHIVE) { }
- };
-
- class AsNeededOption : public PositionDependentOption {
- public:
- AsNeededOption(unsigned pPosition)
- : PositionDependentOption(pPosition,
- PositionDependentOption::AS_NEEDED) { }
- };
-
- class NoAsNeededOption : public PositionDependentOption {
- public:
- NoAsNeededOption(unsigned pPosition)
- : PositionDependentOption(pPosition,
- PositionDependentOption::NO_AS_NEEDED) { }
- };
-
- class AddNeededOption : public PositionDependentOption {
- public:
- AddNeededOption(unsigned pPosition)
- : PositionDependentOption(pPosition,
- PositionDependentOption::ADD_NEEDED) { }
- };
-
- class NoAddNeededOption : public PositionDependentOption {
- public:
- NoAddNeededOption(unsigned pPosition)
- : PositionDependentOption(pPosition,
- PositionDependentOption::NO_ADD_NEEDED) { }
- };
-
- class BDynamicOption : public PositionDependentOption {
- public:
- BDynamicOption(unsigned pPosition)
- : PositionDependentOption(pPosition,
- PositionDependentOption::BDYNAMIC) { }
- };
-
- class BStaticOption : public PositionDependentOption {
- public:
- BStaticOption(unsigned pPosition)
- : PositionDependentOption(pPosition,
- PositionDependentOption::BSTATIC) { }
- };
-
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Support/FileHandle.h b/include/mcld/Support/FileHandle.h
index f6881c3..3b4fe81 100644
--- a/include/mcld/Support/FileHandle.h
+++ b/include/mcld/Support/FileHandle.h
@@ -13,10 +13,11 @@
#endif
#include <mcld/Support/Path.h>
#include <mcld/ADT/Flags.h>
+
+#include <sys/stat.h>
#include <errno.h>
-namespace mcld
-{
+namespace mcld {
/** \class FileHandle
* \brief FileHandle class provides an interface for reading from and writing
@@ -53,15 +54,16 @@
enum PermissionEnum
{
- ReadOwner = 0x0400,
- WriteOwner = 0x0200,
- ExeOwner = 0x0100,
- ReadGroup = 0x0040,
- WriteGroup = 0x0020,
- ExeGroup = 0x0010,
- ReadOther = 0x0004,
- WriteOther = 0x0002,
- ExeOther = 0x0001
+ ReadOwner = S_IRUSR,
+ WriteOwner = S_IWUSR,
+ ExeOwner = S_IXUSR,
+ ReadGroup = S_IRGRP,
+ WriteGroup = S_IWGRP,
+ ExeGroup = S_IXGRP,
+ ReadOther = S_IROTH,
+ WriteOther = S_IWOTH,
+ ExeOther = S_IXOTH,
+ System = 0xFFFFFFFF
};
typedef Flags<PermissionEnum> Permission;
@@ -71,12 +73,12 @@
~FileHandle();
- bool open(const sys::fs::Path& pPath,
- OpenMode pMode);
-
+ /// open - open the file.
+ /// @return if we meet any trouble during opening the file, return false.
+ /// use rdstate() to see what happens.
bool open(const sys::fs::Path& pPath,
OpenMode pMode,
- Permission pPerm);
+ Permission pPerm = System);
bool delegate(int pFD, OpenMode pMode = Unknown);
diff --git a/include/mcld/Support/GCFactoryListTraits.h b/include/mcld/Support/GCFactoryListTraits.h
index 418ec57..8a768c8 100644
--- a/include/mcld/Support/GCFactoryListTraits.h
+++ b/include/mcld/Support/GCFactoryListTraits.h
@@ -25,11 +25,13 @@
* the nodes in the list is produced by GCFactory.
*/
template<typename DataType>
-class GCFactoryListTraits : public llvm::ilist_default_traits<DataType> {
+class GCFactoryListTraits : public llvm::ilist_default_traits<DataType>
+{
private:
- class SentinelNode : public llvm::ilist_node<DataType> {
+ class SentinelNode : public DataType
+ {
public:
- SentinelNode() : llvm::ilist_node<DataType>() { }
+ SentinelNode() { }
};
public:
diff --git a/include/mcld/Support/MemoryArea.h b/include/mcld/Support/MemoryArea.h
index 5337f48..a735f62 100644
--- a/include/mcld/Support/MemoryArea.h
+++ b/include/mcld/Support/MemoryArea.h
@@ -6,34 +6,27 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_MEMORY_AREA_H
-#define MCLD_MEMORY_AREA_H
+#ifndef MCLD_SUPPORT_MEMORY_AREA_H
+#define MCLD_SUPPORT_MEMORY_AREA_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <mcld/ADT/Uncopyable.h>
-#include <mcld/Support/Path.h>
-#include <mcld/Support/FileSystem.h>
-#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/Space.h>
-#include <fcntl.h>
-#include <string>
-#include <list>
-
+#include <cstddef>
+#include <map>
#if defined(ENABLE_UNITTEST)
-namespace mcldtest
-{
+namespace mcldtest {
class MemoryAreaTest;
} // namespace of mcldtest
#endif
-namespace mcld
-{
+namespace mcld {
+class Space;
+class FileHandle;
class MemoryRegion;
-class RegionFactory;
/** \class MemoryArea
* \brief MemoryArea is used to manage distinct MemoryRegions of address space.
@@ -55,19 +48,16 @@
{
friend class MemoryAreaFactory;
public:
- typedef llvm::iplist<Space> SpaceList;
-
-public:
// constructor by file handler.
// If the given file handler is read-only, client can not request a region
// that out of the file size.
// @param pFileHandle - file handler
- MemoryArea(RegionFactory& pRegionFactory, FileHandle& pFileHandle);
+ explicit MemoryArea(FileHandle& pFileHandle);
// constructor by set universal space.
// Client can not request a region that out of the universal space.
// @param pUniverse - file handler
- MemoryArea(RegionFactory& pRegionFactory, Space& pUniverse);
+ explicit MemoryArea(Space& pUniverse);
// destructor
~MemoryArea();
@@ -85,11 +75,10 @@
// clear - release all memory regions.
void clear();
- FileHandle* handler()
- { return m_pFileHandle; }
+ const FileHandle* handler() const { return m_pFileHandle; }
+ FileHandle* handler() { return m_pFileHandle; }
- const FileHandle* handler() const
- { return m_pFileHandle; }
+ bool hasHandler() const { return (NULL != m_pFileHandle); }
// ----- space list methods ----- //
Space* find(size_t pOffset, size_t pLength);
@@ -97,8 +86,34 @@
const Space* find(size_t pOffset, size_t pLength) const;
private:
- RegionFactory& m_RegionFactory;
- SpaceList m_SpaceList;
+ 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::map<Key, Space*, Key::Compare> SpaceMapType;
+
+private:
+ SpaceMapType m_SpaceMap;
FileHandle* m_pFileHandle;
};
diff --git a/include/mcld/Support/MemoryAreaFactory.h b/include/mcld/Support/MemoryAreaFactory.h
index be86b8c..b28f096 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_MEMORY_AREA_FACTORY_H
-#define MCLD_MEMORY_AREA_FACTORY_H
+#ifndef MCLD_SUPPORT_MEMORY_AREA_FACTORY_H
+#define MCLD_SUPPORT_MEMORY_AREA_FACTORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
@@ -20,7 +20,6 @@
namespace mcld
{
-class RegionFactory;
/** \class MemoryAreaFactory
* \brief MemoryAreaFactory avoids creating duplicated MemoryAreas of the
* same file.
@@ -55,19 +54,18 @@
FileHandle::OpenMode pMode,
FileHandle::Permission pPerm);
- void destruct(MemoryArea* pArea);
-
-protected:
// Create a MemoryArea with an universal space.
// The created MemoryArea is not moderated by m_HandleToArea.
- MemoryArea* create(void* pMemBuffer, size_t pSize);
+ MemoryArea* produce(void* pMemBuffer, size_t pSize);
// Create a MemoryArea by the given file handler
- MemoryArea* create(int pFD, FileHandle::OpenMode pMode);
+ // The created MemoryArea is not moderated by m_HandleToArea.
+ MemoryArea* produce(int pFD, FileHandle::OpenMode pMode);
+
+ void destruct(MemoryArea* pArea);
private:
HandleToArea m_HandleToArea;
- RegionFactory* m_pRegionFactory;
};
} // namespace of mcld
diff --git a/include/mcld/Support/MemoryRegion.h b/include/mcld/Support/MemoryRegion.h
index caa929f..0984873 100644
--- a/include/mcld/Support/MemoryRegion.h
+++ b/include/mcld/Support/MemoryRegion.h
@@ -12,13 +12,14 @@
#include <gtest.h>
#endif
+#include <mcld/Config/Config.h>
#include <mcld/ADT/Uncopyable.h>
-#include <mcld/Support/FileSystem.h>
-#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/Allocators.h>
#include <mcld/Support/Space.h>
-namespace mcld
-{
+namespace mcld {
+
+class MemoryArea;
/** \class MemoryRegion
* \brief MemoryRegion is a range of virtual memory which is mapped onto a
@@ -35,6 +36,7 @@
*/
class MemoryRegion : private Uncopyable
{
+friend class Chunk<MemoryRegion, MCLD_REGION_CHUNK_SIZE>;
friend class RegionFactory;
friend class MemoryArea;
@@ -43,40 +45,68 @@
typedef Space::ConstAddress ConstAddress;
private:
- MemoryRegion(Space& pParent, const Address pVMAStart, size_t pSize);
+ MemoryRegion();
- Space* parent()
- { return &m_Parent; }
+ MemoryRegion(const Address pVMAStart, size_t pSize);
- const Space* parent() const
- { return &m_Parent; }
-
-public:
~MemoryRegion();
- Address start()
- { return m_VMAStart; }
+ void setParent(Space& pSpace) { m_pParent = &pSpace; }
- ConstAddress start() const
- { return m_VMAStart; }
+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);
- Address end()
- { return m_VMAStart+m_Length; }
+ /// 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);
- ConstAddress end() const
- { return m_VMAStart+m_Length; }
+ /// 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);
- size_t size() const
- { return m_Length; }
+ const Space* parent() const { return m_pParent; }
+ Space* parent() { return m_pParent; }
- Address getBuffer(size_t pOffset = 0)
- { return m_VMAStart+pOffset; }
+ 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_Parent;
+ Space* m_pParent;
Address m_VMAStart;
size_t m_Length;
};
diff --git a/include/mcld/Support/MsgHandling.h b/include/mcld/Support/MsgHandling.h
index a42bb54..d00132c 100644
--- a/include/mcld/Support/MsgHandling.h
+++ b/include/mcld/Support/MsgHandling.h
@@ -13,16 +13,18 @@
#endif
#include <mcld/LD/MsgHandler.h>
-namespace mcld
-{
+namespace mcld {
-class MCLDInfo;
+class LinkerConfig;
class DiagnosticPrinter;
class DiagnosticLineInfo;
-void InitializeDiagnosticEngine(const MCLDInfo& pLDInfo,
- DiagnosticLineInfo* pLineInfo,
- DiagnosticPrinter* pPrinter);
+void InitializeDiagnosticEngine(const LinkerConfig& pConfig,
+ DiagnosticPrinter* pPrinter = NULL);
+
+void FinalizeDiagnosticEngine();
+
+bool Diagnose();
DiagnosticEngine& getDiagnosticEngine();
@@ -38,6 +40,7 @@
//===----------------------------------------------------------------------===//
// Inline functions
+//===----------------------------------------------------------------------===//
inline mcld::MsgHandler mcld::unreachable(unsigned int pID)
{
return getDiagnosticEngine().report(pID, DiagnosticEngine::Unreachable);
diff --git a/include/mcld/Support/Path.h b/include/mcld/Support/Path.h
index de49d3e..b53cd1a 100644
--- a/include/mcld/Support/Path.h
+++ b/include/mcld/Support/Path.h
@@ -89,6 +89,7 @@
// ----- decomposition ----- //
Path parent_path() const;
+ Path filename() const;
Path stem() const;
Path extension() const;
diff --git a/include/mcld/Support/PositionDependentOption.h b/include/mcld/Support/PositionDependentOption.h
deleted file mode 100644
index 8dd969d..0000000
--- a/include/mcld/Support/PositionDependentOption.h
+++ /dev/null
@@ -1,69 +0,0 @@
-//===- PositionDependentOption.h ------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MCLD_POSITIONDEPENDENTOPTION_H
-#define MCLD_POSITIONDEPENDENTOPTION_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-
-#include <vector>
-
-namespace mcld
-{
-
- /** \class PositionDependentOption
- * \brief PositionDependentOptions converts LLVM options into MCLDInfo
- */
- class PositionDependentOption
- {
- public:
- enum Type {
- BITCODE,
- NAMESPEC,
- INPUT_FILE,
- START_GROUP,
- END_GROUP,
- WHOLE_ARCHIVE,
- NO_WHOLE_ARCHIVE,
- AS_NEEDED,
- NO_AS_NEEDED,
- ADD_NEEDED,
- NO_ADD_NEEDED,
- BDYNAMIC,
- BSTATIC
- };
-
- protected:
- PositionDependentOption(unsigned int pPosition, Type pType)
- : m_Type(pType),
- m_Position(pPosition) {}
-
- public:
- Type type()
- { return m_Type; }
-
- Type type() const
- { return m_Type; }
-
- unsigned int position()
- { return m_Position; }
-
- unsigned int position() const
- { return m_Position; }
-
- private:
- Type m_Type;
- unsigned int m_Position;
- };
-
- typedef std::vector<PositionDependentOption*> PositionDependentOptions;
-} // namespace of mcld
-
-#endif
-
diff --git a/include/mcld/Support/RegionFactory.h b/include/mcld/Support/RegionFactory.h
index 8893500..fd90186 100644
--- a/include/mcld/Support/RegionFactory.h
+++ b/include/mcld/Support/RegionFactory.h
@@ -6,18 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_REGION_FACTORY_H
-#define MCLD_REGION_FACTORY_H
+#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>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/FileSystem.h>
-namespace mcld
-{
+namespace mcld {
class MemoryArea;
@@ -25,17 +23,15 @@
* \brief RegionFactory produces and destroys MemoryRegions
*
*/
-class RegionFactory : public GCFactory<MemoryRegion, 0>
+class RegionFactory : public GCFactory<MemoryRegion, MCLD_REGION_CHUNK_SIZE>
{
public:
- typedef GCFactory<MemoryRegion, 0> Alloc;
+ typedef GCFactory<MemoryRegion, MCLD_REGION_CHUNK_SIZE> Alloc;
+ typedef MemoryRegion::Address Address;
+ typedef MemoryRegion::ConstAddress ConstAddress;
public:
- RegionFactory(size_t pNum);
- ~RegionFactory();
-
- // ----- production ----- //
- MemoryRegion* produce(Space& pSpace, void* pVMAStart, size_t pSize);
+ MemoryRegion* produce(Address pVMAStart, size_t pSize);
void destruct(MemoryRegion* pRegion);
};
diff --git a/include/mcld/Support/Space.h b/include/mcld/Support/Space.h
index 7ebedce..cdf69b0 100644
--- a/include/mcld/Support/Space.h
+++ b/include/mcld/Support/Space.h
@@ -12,12 +12,9 @@
#include <gtest.h>
#endif
#include <llvm/Support/DataTypes.h>
-#include <llvm/ADT/ilist.h>
-#include <llvm/ADT/ilist_node.h>
#include <mcld/ADT/TypeTraits.h>
-namespace mcld
-{
+namespace mcld {
class FileHandle;
class MemoryRegion;
@@ -27,7 +24,7 @@
* the other Space.
*
*/
-class Space : public llvm::ilist_node<Space>
+class Space
{
public:
enum Type
@@ -41,20 +38,13 @@
typedef NonConstTraits<uint8_t>::pointer Address;
typedef ConstTraits<uint8_t>::pointer ConstAddress;
-// llvm::iplist functions
-public:
- // llvm::iplist needs default constructor to make a sentinel.
- // Normal users should use @ref Space::createSpace function.
+private:
Space();
- // llvm::iplist needs public destructor to delete the sentinel.
- // Normal users should use @ref Space::releaseSpace function.
~Space();
- // This constructor is opened for the clients who want to control the
- // details. In MCLinker, this constructor is used no where.
Space(Type pType, void* pMemBuffer, size_t pSize);
-
+
public:
void setStart(size_t pOffset)
{ m_StartOffset = pOffset; }
@@ -83,12 +73,17 @@
size_t numOfRegions() const
{ return m_RegionCount; }
- static Space* createSpace(FileHandle& pHandler,
- size_t pOffset, size_t pSize);
-
- static void releaseSpace(Space* pSpace, FileHandle& pHandler);
+ /// Create - Create a Space from external memory
+ static Space* Create(void* pMemBuffer, size_t pSize);
- static void syncSpace(Space* pSpace, FileHandle& pHandler);
+ /// 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;
diff --git a/include/mcld/Support/TargetRegistry.h b/include/mcld/Support/TargetRegistry.h
index 8d0fee8..560a61e 100644
--- a/include/mcld/Support/TargetRegistry.h
+++ b/include/mcld/Support/TargetRegistry.h
@@ -20,10 +20,13 @@
} // namespace of llvm
namespace mcld {
-class LLVMTargetMachine;
+
+class Module;
+class LinkerConfig;
+class MemoryArea;
+class MCLDTargetMachine;
class TargetRegistry;
-class SectLinker;
-class SectLinkerOption;
+class MCLinker;
class TargetLDBackend;
class AttributeFactory;
class InputFactory;
@@ -32,22 +35,25 @@
//===----------------------------------------------------------------------===//
/// Target - mcld::Target is an object adapter of llvm::Target
-///
+//===----------------------------------------------------------------------===//
class Target
{
- friend class mcld::LLVMTargetMachine;
+ friend class mcld::MCLDTargetMachine;
friend class mcld::TargetRegistry;
public:
- typedef mcld::LLVMTargetMachine *(*TargetMachineCtorTy)(const mcld::Target &,
+ typedef mcld::MCLDTargetMachine *(*TargetMachineCtorTy)(const mcld::Target &,
llvm::TargetMachine &,
const std::string&);
- typedef SectLinker *(*SectLinkerCtorTy)(const std::string& pTriple,
- SectLinkerOption &,
- TargetLDBackend&);
+ typedef MCLinker *(*MCLinkerCtorTy)(const std::string& pTriple,
+ LinkerConfig&,
+ Module&,
+ MemoryArea& pOutput);
+
+ typedef bool (*EmulationFnTy)(const std::string& pTriple, LinkerConfig&);
typedef TargetLDBackend *(*TargetLDBackendCtorTy)(const llvm::Target&,
- const std::string&);
+ const LinkerConfig&);
typedef DiagnosticLineInfo *(*DiagnosticLineInfoCtorTy)(const mcld::Target&,
const std::string&);
@@ -58,7 +64,7 @@
void setTarget(const llvm::Target& pTarget)
{ m_pT = &pTarget; }
- mcld::LLVMTargetMachine *createTargetMachine(const std::string &pTriple,
+ 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,
@@ -73,27 +79,34 @@
return NULL;
}
- /// createSectLinker - create target-specific SectLinker
+ /// createMCLinker - create target-specific MCLinker
///
- /// @return created SectLinker
- SectLinker *createSectLinker(const std::string &pTriple,
- SectLinkerOption &pOption,
- TargetLDBackend &pLDBackend) const {
- if (!SectLinkerCtorFn)
+ /// @return created MCLinker
+ MCLinker *createMCLinker(const std::string &pTriple,
+ LinkerConfig& pConfig,
+ Module& pModule,
+ MemoryArea& pOutput) const {
+ if (!MCLinkerCtorFn)
return NULL;
- return SectLinkerCtorFn(pTriple,
- pOption,
- pLDBackend);
+ return MCLinkerCtorFn(pTriple, pConfig, pModule, pOutput);
+ }
+
+ /// emulate - given MCLinker default values for the other aspects of the
+ /// target system.
+ bool emulate(const std::string& pTriple, LinkerConfig& pConfig) const {
+ if (!EmulationFn)
+ return false;
+ return EmulationFn(pTriple, pConfig);
}
/// createLDBackend - create target-specific LDBackend
///
/// @return created TargetLDBackend
- TargetLDBackend* createLDBackend(const std::string& Triple) const
+ TargetLDBackend* createLDBackend(const LinkerConfig& pConfig) const
{
if (!TargetLDBackendCtorFn)
return NULL;
- return TargetLDBackendCtorFn(*get(), Triple);
+ return TargetLDBackendCtorFn(*get(), pConfig);
}
/// createDiagnosticLineInfo - create target-specific DiagnosticLineInfo
@@ -105,13 +118,13 @@
return DiagnosticLineInfoCtorFn(pTarget, pTriple);
}
- const llvm::Target* get() const
- { return m_pT; }
+ const llvm::Target* get() const { return m_pT; }
private:
// ----- function pointers ----- //
TargetMachineCtorTy TargetMachineCtorFn;
- SectLinkerCtorTy SectLinkerCtorFn;
+ MCLinkerCtorTy MCLinkerCtorFn;
+ EmulationFnTy EmulationFn;
TargetLDBackendCtorTy TargetLDBackendCtorFn;
DiagnosticLineInfoCtorTy DiagnosticLineInfoCtorFn;
@@ -161,15 +174,26 @@
T.TargetMachineCtorFn = Fn;
}
- /// RegisterSectLinker - Register a SectLinker implementation for the given
+ /// RegisterMCLinker - Register a MCLinker implementation for the given
/// target.
///
/// @param T - the target being registered
- /// @param Fn - A function to create SectLinker for the target
- static void RegisterSectLinker(mcld::Target &T, mcld::Target::SectLinkerCtorTy Fn)
+ /// @param Fn - A function to create MCLinker for the target
+ static void RegisterMCLinker(mcld::Target &T, mcld::Target::MCLinkerCtorTy Fn)
{
- if (!T.SectLinkerCtorFn)
- T.SectLinkerCtorFn = Fn;
+ if (!T.MCLinkerCtorFn)
+ T.MCLinkerCtorFn = Fn;
+ }
+
+ /// RegisterEmulation - Register a emulation function for the target.
+ /// target.
+ ///
+ /// @param T - the target being registered
+ /// @param Fn - A emulation function
+ static void RegisterEmulation(mcld::Target &T, mcld::Target::EmulationFnTy Fn)
+ {
+ if (!T.EmulationFn)
+ T.EmulationFn = Fn;
}
/// RegisterTargetLDBackend - Register a TargetLDBackend implementation for
@@ -214,7 +238,7 @@
///
/// Target TheFooTarget; // The global target instance.
///
-/// extern "C" void LLVMInitializeFooTargetInfo() {
+/// extern "C" void MCLDInitializeFooTargetInfo() {
/// RegisterTarget X(TheFooTarget, "foo", "Foo description");
/// }
struct RegisterTarget
@@ -226,7 +250,9 @@
if( 0==strcmp(TIter->getName(), Name) )
break;
}
- T.setTarget(*TIter);
+
+ if (TIter != TEnd)
+ T.setTarget(*TIter);
TargetRegistry::RegisterTarget(T);
}
@@ -236,7 +262,7 @@
/// implementation, for use in the target machine initialization
/// function. Usage:
///
-/// extern "C" void LLVMInitializeFooTarget() {
+/// extern "C" void MCLDInitializeFooTarget() {
/// extern mcld::Target TheFooTarget;
/// RegisterTargetMachine<mcld::FooTargetMachine> X(TheFooTarget);
/// }
@@ -248,7 +274,7 @@
}
private:
- static mcld::LLVMTargetMachine *Allocator(const mcld::Target &T,
+ static mcld::MCLDTargetMachine *Allocator(const mcld::Target &T,
llvm::TargetMachine& TM,
const std::string &Triple) {
return new TargetMachineImpl(TM, T, Triple);
diff --git a/include/mcld/Support/TargetSelect.h b/include/mcld/Support/TargetSelect.h
index 0788d1d..7fcb74a 100644
--- a/include/mcld/Support/TargetSelect.h
+++ b/include/mcld/Support/TargetSelect.h
@@ -14,27 +14,31 @@
extern "C" {
// Declare all of the target-initialization functions that are available.
-#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##LDTargetInfo();
+#define MCLD_TARGET(TargetName) void MCLDInitialize##TargetName##LDTargetInfo();
#include "mcld/Config/Targets.def"
// Declare all of the target-dependent functions that are available.
-#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##LDTarget();
+#define MCLD_TARGET(TargetName) void MCLDInitialize##TargetName##LDTarget();
#include "mcld/Config/Targets.def"
// Declare all of the target-depedent linker information
-#define LLVM_LINKER(TargetName) void LLVMInitialize##TargetName##LDInfo();
+#define MCLD_LINKER(TargetName) void MCLDInitialize##TargetName##LDInfo();
#include "mcld/Config/Linkers.def"
// Declare all of the available linker environment.
-#define LLVM_LINKER(TargetName) void LLVMInitialize##TargetName##SectLinker();
+#define MCLD_LINKER(TargetName) void MCLDInitialize##TargetName##MCLinker();
#include "mcld/Config/Linkers.def"
+ // Declare all of the available emulators.
+#define MCLD_TARGET(TargetName) void MCLDInitialize##TargetName##Emulation();
+#include "mcld/Config/Targets.def"
+
// Declare all of the available target-specific linker
-#define LLVM_LINKER(TargetName) void LLVMInitialize##TargetName##LDBackend();
+#define MCLD_LINKER(TargetName) void MCLDInitialize##TargetName##LDBackend();
#include "mcld/Config/Linkers.def"
// Declare all of the available target-specific diagnostic line infomation
-#define LLVM_LINKER(TargetName) void LLVMInitialize##TargetName##DiagnosticLineInfo();
+#define MCLD_LINKER(TargetName) void MCLDInitialize##TargetName##DiagnosticLineInfo();
#include "mcld/Config/Linkers.def"
} // extern "C"
@@ -42,37 +46,45 @@
namespace mcld
{
/// InitializeAllTargetInfos - The main program should call this function if
- /// it wants access to all available targets that LLVM is configured to
+ /// it wants access to all available targets that MCLD is configured to
/// support, to make them available via the TargetRegistry.
///
/// It is legal for a client to make multiple calls to this function.
inline void InitializeAllTargetInfos() {
-#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##LDTargetInfo();
+#define MCLD_TARGET(TargetName) MCLDInitialize##TargetName##LDTargetInfo();
#include "mcld/Config/Targets.def"
}
/// InitializeAllTargets - The main program should call this function if it
- /// wants access to all available target machines that LLVM is configured to
+ /// wants access to all available target machines that MCLD is configured to
/// support, to make them available via the TargetRegistry.
///
/// It is legal for a client to make multiple calls to this function.
inline void InitializeAllTargets() {
mcld::InitializeAllTargetInfos();
-#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##LDTarget();
+#define MCLD_TARGET(TargetName) MCLDInitialize##TargetName##LDBackend();
#include "mcld/Config/Targets.def"
+ }
-#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##LDBackend();
+ /// InitializeAllEmulations - The main program should call this function if
+ /// it wants all emulations to be configured to support. This function makes
+ /// all emulations available via the TargetRegistry.
+ inline void InitializeAllEmulations() {
+#define MCLD_TARGET(TargetName) MCLDInitialize##TargetName##Emulation();
#include "mcld/Config/Targets.def"
}
/// InitializeAllLinkers - The main program should call this function if it
- /// wants all linkers that LLVM is configured to support, to make them
+ /// wants all linkers that is configured to support, to make them
/// available via the TargetRegistry.
///
/// It is legal for a client to make multiple calls to this function.
inline void InitializeAllLinkers() {
-#define LLVM_LINKER(TargetName) LLVMInitialize##TargetName##SectLinker();
+#define MCLD_TARGET(TargetName) MCLDInitialize##TargetName##LDTarget();
+#include "mcld/Config/Targets.def"
+
+#define MCLD_LINKER(TargetName) MCLDInitialize##TargetName##MCLinker();
#include "mcld/Config/Linkers.def"
}
@@ -80,7 +92,7 @@
/// wants to print linker-specific messages. To make them available via the
/// TargetRegistry.
inline void InitializeAllDiagnostics() {
-#define LLVM_LINKER(TargetName) LLVMInitialize##TargetName##DiagnosticLineInfo();
+#define MCLD_LINKER(TargetName) MCLDInitialize##TargetName##DiagnosticLineInfo();
#include "mcld/Config/Linkers.def"
}
diff --git a/include/mcld/Support/ToolOutputFile.h b/include/mcld/Support/ToolOutputFile.h
new file mode 100644
index 0000000..e0e8752
--- /dev/null
+++ b/include/mcld/Support/ToolOutputFile.h
@@ -0,0 +1,85 @@
+//===- ToolOutputFile.h ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_SUPPORT_TOOL_OUTPUT_FILE_H
+#define MCLD_SUPPORT_TOOL_OUTPUT_FILE_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <string>
+#include <mcld/Support/FileHandle.h>
+
+namespace llvm {
+class formatted_raw_ostream;
+} // end of namespace llvm
+
+namespace mcld {
+
+class Path;
+class FileHandle;
+class MemoryArea;
+class raw_mem_ostream;
+
+/** \class ToolOutputFile
+ * \brief ToolOutputFile contains a raw_mem_ostream and adds extra new
+ * 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().
+ */
+class ToolOutputFile
+{
+public:
+ 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();
+
+ /// 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();
+
+private:
+ class CleanupInstaller
+ {
+ public:
+ explicit CleanupInstaller(const std::string& pFilename);
+
+ ~CleanupInstaller();
+
+ /// Keep - The flag which indicates whether we should not delete the file.
+ bool Keep;
+
+ private:
+ std::string m_Filename;
+ };
+
+private:
+ FileHandle m_FileHandle;
+ CleanupInstaller m_Installer;
+ MemoryArea* m_pMemoryArea;
+ raw_mem_ostream* m_pOStream;
+ llvm::formatted_raw_ostream* m_pFOStream;
+
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/include/mcld/Support/raw_mem_ostream.h b/include/mcld/Support/raw_mem_ostream.h
new file mode 100644
index 0000000..b2db64a
--- /dev/null
+++ b/include/mcld/Support/raw_mem_ostream.h
@@ -0,0 +1,51 @@
+//===- 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 61706de..9b52578 100644
--- a/include/mcld/Support/raw_ostream.h
+++ b/include/mcld/Support/raw_ostream.h
@@ -13,10 +13,8 @@
#endif
#include <string>
#include <llvm/Support/raw_ostream.h>
-#include <mcld/MC/MCLDInfo.h>
-namespace mcld
-{
+namespace mcld {
class raw_fd_ostream : public llvm::raw_fd_ostream
{
@@ -33,18 +31,15 @@
/// output errors).
raw_fd_ostream(const char *pFilename,
std::string &pErrorInfo,
- unsigned int pFlags = 0,
- const MCLDInfo* pLDInfo = NULL);
+ unsigned int pFlags = 0);
/// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If
/// ShouldClose is true, this closes the file when the stream is destroyed.
- raw_fd_ostream(int pFD, bool pShouldClose,
- bool pUnbuffered=false,
- const MCLDInfo* pLDInfo = NULL);
+ raw_fd_ostream(int pFD, bool pShouldClose, bool pUnbuffered=false);
virtual ~raw_fd_ostream();
- void setLDInfo(const MCLDInfo& pLDInfo);
+ void setColor(bool pEnable = true);
llvm::raw_ostream &changeColor(enum llvm::raw_ostream::Colors pColors,
@@ -53,20 +48,16 @@
llvm::raw_ostream &resetColor();
- // FIXME: migrate to newer LLVM
- // llvm::raw_ostream &reverseColor();
+ llvm::raw_ostream &reverseColor();
bool is_displayed() const;
private:
- const MCLDInfo* m_pLDInfo;
+ bool m_bConfigColor : 1;
+ bool m_bSetColor : 1;
};
-/// InitializeOStreams - This initialize mcld::outs() and mcld::errs().
-/// Call it before you use mcld::outs() and mcld::errs().
-void InitializeOStreams(const MCLDInfo& pLDInfo);
-
/// outs() - This returns a reference to a raw_ostream for standard output.
/// Use it like: outs() << "foo" << "bar";
mcld::raw_fd_ostream &outs();
diff --git a/include/mcld/Target/ELFDynamic.h b/include/mcld/Target/ELFDynamic.h
index ed18dc0..2298bfd 100644
--- a/include/mcld/Target/ELFDynamic.h
+++ b/include/mcld/Target/ELFDynamic.h
@@ -22,7 +22,7 @@
class GNULDBackend;
class ELFFileFormat;
-class MCLDInfo;
+class LinkerConfig;
class MemoryRegion;
namespace elf_dynamic {
@@ -37,7 +37,7 @@
EntryIF();
public:
- virtual ~EntryIF();
+ virtual ~EntryIF();
virtual EntryIF* clone() const = 0;
virtual size_t size() const = 0;
@@ -87,7 +87,7 @@
private:
Pair m_Pair;
-};
+};
#include "ELFDynamic.tcc"
@@ -116,14 +116,14 @@
size_t numOfBytes() const;
/// reserveEntries - reserve entries
- void reserveEntries(const MCLDInfo& pInfo,
+ void reserveEntries(const LinkerConfig& pConfig,
const ELFFileFormat& pFormat);
/// reserveNeedEntry - reserve on DT_NEED entry.
void reserveNeedEntry();
-
+
/// applyEntries - apply entries
- void applyEntries(const MCLDInfo& pInfo,
+ void applyEntries(const LinkerConfig& pConfig,
const ELFFileFormat& pFormat);
void applySoname(uint64_t pStrTabIdx);
@@ -161,6 +161,7 @@
EntryListType m_EntryList;
EntryListType m_NeedList;
elf_dynamic::EntryIF* m_pEntryFactory;
+ const GNULDBackend& m_Backend;
// The entry reserved and the entry being applied are not must matched.
// For better performance, we use a simple counter and apply entry one-by-one
diff --git a/include/mcld/Target/Stub.h b/include/mcld/Target/ELFEmulation.h
similarity index 60%
rename from include/mcld/Target/Stub.h
rename to include/mcld/Target/ELFEmulation.h
index 3bc778f..341b2e8 100644
--- a/include/mcld/Target/Stub.h
+++ b/include/mcld/Target/ELFEmulation.h
@@ -1,4 +1,4 @@
-//===- Stub.h -------------------------------------------------------------===//
+//===- ELFEmulation.h -----------------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,23 +6,17 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef LD_STUB_H
-#define LD_STUB_H
+#ifndef MCLD_ELF_EMULATION_H
+#define MCLD_ELF_EMULATION_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include "mcld/LD/Relocation.h"
-namespace mcld
-{
+namespace mcld {
-/** \class Stub
- * \brief Stub is a piece of jumpping code.
- */
-class Stub
-{
+class LinkerConfig;
-};
+bool MCLDEmulateELF(LinkerConfig& pConfig);
} // namespace of mcld
diff --git a/include/mcld/Target/ELFSectLinker.h b/include/mcld/Target/ELFMCLinker.h
similarity index 60%
rename from include/mcld/Target/ELFSectLinker.h
rename to include/mcld/Target/ELFMCLinker.h
index 04234a8..76f46e8 100644
--- a/include/mcld/Target/ELFSectLinker.h
+++ b/include/mcld/Target/ELFMCLinker.h
@@ -1,4 +1,4 @@
-//===- ELFSectLinker.h ----------------------------------------------------===//
+//===- ELFMCLinker.h ------------------------------------------------------===//
//
// The MCLinker Project
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// ELFSectLinker is a customized linker pass for ELF platform.
+// ELFMCLinker is a customized linker pass for ELF platform.
// This pass set up default parameters for ELF.
//
//===----------------------------------------------------------------------===//
@@ -16,18 +16,21 @@
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
-#include <mcld/CodeGen/SectLinker.h>
+#include <mcld/CodeGen/MCLinker.h>
-namespace mcld
-{
+namespace mcld {
-class ELFSectLinker : public SectLinker
+class Module;
+class Output;
+
+class ELFMCLinker : public MCLinker
{
public:
- ELFSectLinker(SectLinkerOption &pOption,
- mcld::TargetLDBackend &pLDBackend);
+ ELFMCLinker(LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ MemoryArea& pOutput);
- virtual ~ELFSectLinker();
+ virtual ~ELFMCLinker();
};
} // namespace of mcld
diff --git a/include/mcld/Target/GNULDBackend.h b/include/mcld/Target/GNULDBackend.h
index d05fe72..4623e33 100644
--- a/include/mcld/Target/GNULDBackend.h
+++ b/include/mcld/Target/GNULDBackend.h
@@ -11,46 +11,36 @@
#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/EhFrameHdr.h>
#include <mcld/LD/ELFDynObjFileFormat.h>
+#include <mcld/LD/ELFExecFileFormat.h>
+#include <mcld/LD/ELFObjectFileFormat.h>
+#include <mcld/LD/GNUArchiveReader.h>
+#include <mcld/LD/ELFObjectReader.h>
#include <mcld/LD/ELFDynObjReader.h>
#include <mcld/LD/ELFDynObjWriter.h>
-#include <mcld/LD/ELFExecFileFormat.h>
#include <mcld/LD/ELFExecWriter.h>
-#include <mcld/LD/ELFObjectReader.h>
#include <mcld/LD/ELFObjectWriter.h>
#include <mcld/LD/ELFSegment.h>
#include <mcld/LD/ELFSegmentFactory.h>
-#include <mcld/LD/GNUArchiveReader.h>
-#include <mcld/Support/GCFactory.h>
#include <mcld/Target/ELFDynamic.h>
-#include <mcld/Target/TargetLDBackend.h>
-namespace mcld
-{
+#include <mcld/Support/GCFactory.h>
+#include <mcld/Module.h>
-struct SymCompare
-{
- bool operator()(const LDSymbol* X, const LDSymbol* Y) const
- { return (X==Y); }
-};
+namespace mcld {
-struct PtrHash
-{
- size_t operator()(const LDSymbol* pKey) const
- {
- return (unsigned((uintptr_t)pKey) >> 4) ^
- (unsigned((uintptr_t)pKey) >> 9);
- }
-};
-
-class MCLDInfo;
+class Module;
+class LinkerConfig;
class Layout;
-class SymbolCategory;
+class EhFrame;
+class EhFrameHdr;
+class BranchIslandFactory;
+class StubFactory;
/** \class GNULDBackend
* \brief GNULDBackend provides a common interface for all GNU Unix-OS
@@ -59,82 +49,54 @@
class GNULDBackend : public TargetLDBackend
{
protected:
- GNULDBackend();
+ GNULDBackend(const LinkerConfig& pConfig);
public:
virtual ~GNULDBackend();
// ----- readers/writers ----- //
- bool initArchiveReader(MCLinker& pLinker,
- MCLDInfo& pInfo,
- MemoryAreaFactory& pMemAreaFactory);
- bool initObjectReader(MCLinker& pLinker);
- bool initDynObjReader(MCLinker& pLinker);
- bool initObjectWriter(MCLinker& pLinker);
- bool initDynObjWriter(MCLinker& pLinker);
- bool initExecWriter(MCLinker& pLinker);
-
- GNUArchiveReader *getArchiveReader();
- const GNUArchiveReader *getArchiveReader() const;
-
- ELFObjectReader *getObjectReader();
- const ELFObjectReader *getObjectReader() const;
-
- ELFDynObjReader *getDynObjReader();
- const ELFDynObjReader *getDynObjReader() const;
-
- ELFObjectWriter *getObjectWriter();
- const ELFObjectWriter *getObjectWriter() const;
-
- ELFDynObjWriter *getDynObjWriter();
- const ELFDynObjWriter *getDynObjWriter() const;
-
- ELFExecWriter *getExecWriter();
- const ELFExecWriter *getExecWriter() const;
+ GNUArchiveReader* createArchiveReader(Module& pModule);
+ ELFObjectReader* createObjectReader(FragmentLinker& pLinker);
+ ELFDynObjReader* createDynObjReader(FragmentLinker& pLinker);
+ ELFObjectWriter* createObjectWriter(FragmentLinker& pLinker);
+ ELFDynObjWriter* createDynObjWriter(FragmentLinker& pLinker);
+ ELFExecWriter* createExecWriter(FragmentLinker& pLinker);
// ----- output sections ----- //
- /// initExecSections - initialize sections of the output executable file.
- bool initExecSections(MCLinker& pMCLinker);
-
- /// initDynObjSections - initialize sections of the output shared object.
- bool initDynObjSections(MCLinker& pMCLinker);
+ /// initStdSections - initialize standard sections of the output file.
+ bool initStdSections(ObjectBuilder& pBuilder);
/// getOutputFormat - get the sections of the output file.
- ELFFileFormat* getOutputFormat(const Output& pOutput);
- const ELFFileFormat* getOutputFormat(const Output& pOutput) const;
-
- ELFDynObjFileFormat* getDynObjFileFormat();
- const ELFDynObjFileFormat* getDynObjFileFormat() const;
-
- ELFExecFileFormat* getExecFileFormat();
- const ELFExecFileFormat* getExecFileFormat() const;
+ const ELFFileFormat* getOutputFormat() const;
+ ELFFileFormat* getOutputFormat();
// ----- target symbols ----- //
/// initStandardSymbols - initialize standard symbols.
/// Some section symbols is undefined in input object, and linkers must set
/// up its value. Take __init_array_begin for example. This symbol is an
- /// undefined symbol in input objects. MCLinker must finalize its value
+ /// undefined symbol in input objects. FragmentLinker must finalize its value
/// to the begin of the .init_array section, then relocation enties to
/// __init_array_begin can be applied without emission of "undefined
/// reference to `__init_array_begin'".
- bool initStandardSymbols(MCLinker& pLinker, const Output& pOutput);
+ bool initStandardSymbols(FragmentLinker& pLinker, Module& pModule);
/// finalizeSymbol - Linker checks pSymbol.reserved() if it's not zero,
/// then it will ask backend to finalize the symbol value.
/// @return ture - if backend set the symbol value sucessfully
/// @return false - if backend do not recognize the symbol
- bool finalizeSymbols(MCLinker& pLinker, const Output& pOutput) {
- return (finalizeStandardSymbols(pLinker, pOutput) &&
- finalizeTargetSymbols(pLinker, pOutput));
+ bool finalizeSymbols(FragmentLinker& pLinker) {
+ return (finalizeStandardSymbols(pLinker) &&
+ finalizeTargetSymbols(pLinker));
}
/// finalizeStandardSymbols - set the value of standard symbols
- virtual bool finalizeStandardSymbols(MCLinker& pLinker,
- const Output& pOutput);
+ virtual bool finalizeStandardSymbols(FragmentLinker& pLinker);
/// finalizeTargetSymbols - set the value of target symbols
- virtual bool finalizeTargetSymbols(MCLinker& pLinker,
- const Output& pOutput) = 0;
+ virtual bool finalizeTargetSymbols(FragmentLinker& pLinker) = 0;
+
+ /// finalizeTLSSymbol - set the value of a TLS symbol
+ virtual bool finalizeTLSSymbol(LDSymbol& pSymbol);
size_t sectionStartOffset() const;
@@ -169,42 +131,45 @@
virtual uint64_t defaultTextSegmentAddr() const
{ return 0x0; }
+ bool hasTextRel() const
+ { return m_bHasTextRel; }
+
+ bool hasStaticTLS() const
+ { return m_bHasStaticTLS; }
+
/// segmentStartAddr - this function returns the start address of the segment
- uint64_t segmentStartAddr(const Output& pOutput,
- const MCLDInfo& pInfo) const;
+ uint64_t segmentStartAddr(const FragmentLinker& pLinker) const;
+
+ /// partialScanRelocation - When doing partial linking, fix the relocation
+ /// offset after section merge
+ void partialScanRelocation(Relocation& pReloc,
+ FragmentLinker& pLinker,
+ Module& pModule,
+ const LDSection& pSection);
/// sizeNamePools - compute the size of regular name pools
/// In ELF executable files, regular name pools are .symtab, .strtab.,
/// .dynsym, .dynstr, and .hash
- virtual void sizeNamePools(const Output& pOutput,
- const SymbolCategory& pSymbols,
- const MCLDInfo& pLDInfo);
+ virtual void sizeNamePools(const Module& pModule, bool pIsStaticLink);
/// emitSectionData - emit target-dependent section data
- virtual uint64_t emitSectionData(const Output& pOutput,
- const LDSection& pSection,
- const MCLDInfo& pInfo,
- const Layout& pLayout,
+ virtual uint64_t emitSectionData(const LDSection& pSection,
MemoryRegion& pRegion) const = 0;
/// emitRegNamePools - emit regular name pools - .symtab, .strtab
- virtual void emitRegNamePools(Output& pOutput,
- SymbolCategory& pSymbols,
- const Layout& pLayout,
- const MCLDInfo& pLDInfo);
+ virtual void emitRegNamePools(const Module& pModule,
+ MemoryArea& pOutput);
/// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
- virtual void emitDynNamePools(Output& pOutput,
- SymbolCategory& pSymbols,
- const Layout& pLayout,
- const MCLDInfo& pLDInfo);
+ virtual void emitDynNamePools(const Module& pModule,
+ MemoryArea& 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(const Output& pOutput, const MCLDInfo& pLDInfo);
+ virtual void sizeInterp();
/// emitInterp - emit the .interp
- virtual void emitInterp(Output& pOutput, const MCLDInfo& pLDInfo);
+ virtual void emitInterp(MemoryArea& pOutput);
/// getSectionOrder - compute the layout order of the section
/// Layout calls this function to get the default order of the pSectHdr.
@@ -215,9 +180,7 @@
/// this function.
///
/// @see getTargetSectionOrder
- virtual unsigned int getSectionOrder(const Output& pOutput,
- const LDSection& pSectHdr,
- const MCLDInfo& pInfo) const;
+ virtual unsigned int getSectionOrder(const LDSection& pSectHdr) const;
/// getTargetSectionOrder - compute the layout order of target section
/// If the target favors certain order for the given gSectHdr, please
@@ -225,10 +188,7 @@
///
/// By default, this function returns the maximun order, and pSectHdr
/// will be the last section to be laid out.
- virtual unsigned int
- getTargetSectionOrder(const Output& pOutput,
- const LDSection& pSectHdr,
- const MCLDInfo& pInfo) const
+ virtual unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const
{ return (unsigned int)-1; }
/// numOfSegments - return the number of segments
@@ -248,11 +208,11 @@
/// commonPageSize - the common page size of the target machine, and we set it
/// to 4K here. If target favors the different size, please override this
/// function
- virtual uint64_t commonPageSize(const MCLDInfo& pInfo) const;
+ virtual uint64_t commonPageSize() const;
/// abiPageSize - the abi page size of the target machine, and we set it to 4K
/// here. If target favors the different size, please override this function
- virtual uint64_t abiPageSize(const MCLDInfo& pInfo) const;
+ virtual uint64_t abiPageSize() const;
/// getSymbolIdx - get the symbol index of ouput symbol table
size_t getSymbolIdx(LDSymbol* pSymbol) const;
@@ -265,23 +225,45 @@
/// allocateCommonSymbols - allocate common symbols in the corresponding
/// sections.
/// Different concrete target backend may overlap this function.
- virtual bool allocateCommonSymbols(const MCLDInfo& pLDInfo, MCLinker& pLinker) const;
+ virtual bool allocateCommonSymbols(Module& pModule);
/// isSymbolPreemtible - whether the symbol can be preemted by other
/// link unit
/// @ref Google gold linker, symtab.h:551
- bool isSymbolPreemptible(const ResolveInfo& pSym,
- const MCLDInfo& pLDInfo,
- const Output& pOutput) const;
+ bool isSymbolPreemptible(const ResolveInfo& pSym) const;
/// symbolNeedsDynRel - return whether the symbol needs a dynamic relocation
/// @ref Google gold linker, symtab.h:645
- bool symbolNeedsDynRel(const ResolveInfo& pSym,
+ bool symbolNeedsDynRel(const FragmentLinker& pLinker,
+ const ResolveInfo& pSym,
bool pSymHasPLT,
- const MCLDInfo& pLDInfo,
- const Output& pOutput,
bool isAbsReloc) const;
+ // getTDATASymbol - get section symbol of .tdata
+ LDSymbol& getTDATASymbol();
+ const LDSymbol& getTDATASymbol() const;
+
+ /// getTBSSSymbol - get section symbol of .tbss
+ LDSymbol& getTBSSSymbol();
+ const LDSymbol& getTBSSSymbol() const;
+
+ // ----- relaxation ----- //
+ /// initBRIslandFactory - initialize the branch island factory for relaxation
+ bool initBRIslandFactory();
+
+ /// initStubFactory - initialize the stub factory for relaxation
+ bool initStubFactory();
+
+ /// getBRIslandFactory
+ BranchIslandFactory* getBRIslandFactory() { return m_pBRIslandFactory; }
+
+ /// getStubFactory
+ StubFactory* getStubFactory() { return m_pStubFactory; }
+
+ /// maxBranchOffset - return the max (forward) branch offset of the backend.
+ /// Target can override this function if needed.
+ virtual uint64_t maxBranchOffset() { return (uint64_t)-1; }
+
protected:
uint64_t getSymbolSize(const LDSymbol& pSymbol) const;
@@ -289,7 +271,7 @@
uint64_t getSymbolValue(const LDSymbol& pSymbol) const;
- uint64_t getSymbolShndx(const LDSymbol& pSymbol, const Layout& pLayout) const;
+ uint64_t getSymbolShndx(const LDSymbol& pSymbol) const;
/// getHashBucketCount - calculate hash bucket count.
/// @ref Google gold linker, dynobj.cc:791
@@ -297,35 +279,59 @@
/// isDynamicSymbol
/// @ref Google gold linker: symtab.cc:311
- static bool isDynamicSymbol(const LDSymbol& pSymbol, const Output& pOutput);
+ bool isDynamicSymbol(const LDSymbol& pSymbol);
- /// isOutputPIC - return whether the output is position-independent
- bool isOutputPIC(const Output& pOutput, const MCLDInfo& pInfo) const;
-
- /// isStaticLink - return whether we're doing static link
- bool isStaticLink(const Output& pOutput, const MCLDInfo& pInfo) const;
+ /// isDynamicSymbol
+ /// @ref Google gold linker: symtab.cc:311
+ bool isDynamicSymbol(const ResolveInfo& pResolveInfo);
/// symbolNeedsPLT - return whether the symbol needs a PLT entry
/// @ref Google gold linker, symtab.h:596
- bool symbolNeedsPLT(const ResolveInfo& pSym,
- const MCLDInfo& pLDInfo,
- const Output& pOutput) const;
+ bool symbolNeedsPLT(const FragmentLinker& pLinker,
+ const ResolveInfo& pSym) const;
/// symbolNeedsCopyReloc - return whether the symbol needs a copy relocation
- bool symbolNeedsCopyReloc(const Layout& pLayout,
+ bool symbolNeedsCopyReloc(const FragmentLinker& pLinker,
const Relocation& pReloc,
- const ResolveInfo& pSym,
- const MCLDInfo& pLDInfo,
- const Output& pOutput) const;
+ const ResolveInfo& pSym) const;
+
+ /// symbolHasFinalValue - return true if the symbol's value can be decided at
+ /// link time
+ bool symbolFinalValueIsKnown(const FragmentLinker& pLinker,
+ const ResolveInfo& pSym) const;
+
+ /// emitSymbol32 - emit an ELF32 symbol
+ void emitSymbol32(llvm::ELF::Elf32_Sym& pSym32,
+ LDSymbol& pSymbol,
+ char* pStrtab,
+ size_t pStrtabsize,
+ size_t pSymtabIdx);
+
+ /// emitSymbol64 - emit an ELF64 symbol
+ void emitSymbol64(llvm::ELF::Elf64_Sym& pSym64,
+ LDSymbol& pSymbol,
+ char* pStrtab,
+ size_t pStrtabsize,
+ size_t pSymtabIdx);
+
+ /// checkAndSetHasTextRel - check pSection flag to set HasTextRel
+ void checkAndSetHasTextRel(const LDSection& pSection);
+
+ void setHasStaticTLS(bool pVal = true)
+ { m_bHasStaticTLS = pVal; }
private:
/// createProgramHdrs - base on output sections to create the program headers
- void createProgramHdrs(Output& pOutput,
- const MCLDInfo& pInfo);
+ void createProgramHdrs(Module& pModule, const FragmentLinker& pLinker);
+
+ /// doCreateProgramHdrs - backend can implement this function to create the
+ /// target-dependent segments
+ virtual void doCreateProgramHdrs(Module& pModule,
+ const FragmentLinker& pLinker) = 0;
/// setupProgramHdrs - set up the attributes of segments
/// (i.e., offset, addresses, file/mem size, flag, and alignment)
- void setupProgramHdrs(const Output& pOutput, const MCLDInfo& pInfo);
+ void setupProgramHdrs(const FragmentLinker& pLinker);
/// getSegmentFlag - give a section flag and return the corresponding segment
/// flag
@@ -339,35 +345,39 @@
return flag;
}
- /// createGNUStackInfo - create an output GNU stack section or segment if needed
- void createGNUStackInfo(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker);
+ /// setupGNUStackInfo - setup the section flag of .note.GNU-stack in output
+ void setupGNUStackInfo(Module& pModule, FragmentLinker& pLinker);
+
+ /// setupRelro - setup the offset constraint of PT_RELRO
+ void setupRelro(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);
+
+ /// setOutputSectionOffset - helper function to set output sections' address.
+ void setOutputSectionAddress(FragmentLinker& pLinker,
+ Module& pModule,
+ Module::iterator pSectBegin,
+ Module::iterator pSectEnd);
/// preLayout - Backend can do any needed modification before layout
- void preLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker);
+ void preLayout(Module& pModule, FragmentLinker& pLinker);
/// postLayout -Backend can do any needed modification after layout
- void postLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker);
+ void postLayout(Module& pModule, FragmentLinker& pLinker);
/// preLayout - Backend can do any needed modification before layout
- virtual void doPreLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker) = 0;
+ virtual void doPreLayout(FragmentLinker& pLinker) = 0;
/// postLayout -Backend can do any needed modification after layout
- virtual void doPostLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker) = 0;
+ virtual void doPostLayout(Module& pModule, FragmentLinker& pLinker) = 0;
/// postProcessing - Backend can do any needed modification in the final stage
- void postProcessing(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker);
+ void postProcessing(FragmentLinker& pLinker, MemoryArea& pOutput);
/// dynamic - the dynamic section of the target machine.
virtual ELFDynamic& dynamic() = 0;
@@ -375,6 +385,25 @@
/// dynamic - the dynamic section of the target machine.
virtual const ELFDynamic& dynamic() const = 0;
+ /// relax - the relaxation pass
+ bool relax(Module& pModule, FragmentLinker& pLinker);
+
+ /// mayRelax - Backends should override this function if they need relaxation
+ virtual bool mayRelax() { return false; }
+
+ /// doRelax - Backend can orevride this function to add its relaxation
+ /// implementation. Return true if the output (e.g., .text) is "relaxed"
+ /// (i.e. layout is changed), and set pFinished to true if everything is fit,
+ /// otherwise set it to false.
+ virtual bool doRelax(Module& pModule, FragmentLinker& pLinker, 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
@@ -403,34 +432,64 @@
SHO_SMALL_BSS, // .sbss
SHO_BSS, // .bss
SHO_LARGE_BSS, // .lbss
- SHO_UNDEFINED = ~(0U) // default order
+ SHO_UNDEFINED, // default order
+ SHO_STRTAB // .strtab
};
- typedef HashEntry<LDSymbol*, size_t, SymCompare> HashEntryType;
- typedef HashTable<HashEntryType, PtrHash, EntryFactory<HashEntryType> > HashTableType;
+ struct SymCompare
+ {
+ bool operator()(const LDSymbol* X, const LDSymbol* Y) const
+ { return (X==Y); }
+ };
+
+ struct SymPtrHash
+ {
+ size_t operator()(const LDSymbol* pKey) const
+ {
+ return (unsigned((uintptr_t)pKey) >> 4) ^
+ (unsigned((uintptr_t)pKey) >> 9);
+ }
+ };
+
+ typedef HashEntry<LDSymbol*, size_t, SymCompare> SymHashEntryType;
+ typedef HashTable<SymHashEntryType,
+ SymPtrHash,
+ EntryFactory<SymHashEntryType> > HashTableType;
+
protected:
- // ----- readers and writers ----- //
- GNUArchiveReader* m_pArchiveReader;
ELFObjectReader* m_pObjectReader;
- ELFDynObjReader* m_pDynObjReader;
- ELFObjectWriter* m_pObjectWriter;
- ELFDynObjWriter* m_pDynObjWriter;
- ELFExecWriter* m_pExecWriter;
// ----- file formats ----- //
ELFDynObjFileFormat* m_pDynObjFileFormat;
- ELFExecFileFormat* m_pExecFileFormat;
+ ELFExecFileFormat* m_pExecFileFormat;
+ ELFObjectFileFormat* m_pObjectFileFormat;
// ELF segment factory
ELFSegmentFactory m_ELFSegmentTable;
+ // branch island factory
+ BranchIslandFactory* m_pBRIslandFactory;
+
+ // stub factory
+ StubFactory* m_pStubFactory;
+
// map the LDSymbol to its index in the output symbol table
HashTableType* m_pSymIndexMap;
+ /// m_pEhFrame - section .eh_frame
+ EhFrame* m_pEhFrame;
+
// section .eh_frame_hdr
EhFrameHdr* m_pEhFrameHdr;
+ // ----- dynamic flags ----- //
+ // DF_TEXTREL of DT_FLAGS
+ bool m_bHasTextRel;
+
+ // DF_STATIC_TLS of DT_FLAGS
+ bool m_bHasStaticTLS;
+
// ----- standard symbols ----- //
// section symbols
LDSymbol* f_pPreInitArrayStart;
@@ -440,6 +499,11 @@
LDSymbol* f_pFiniArrayStart;
LDSymbol* f_pFiniArrayEnd;
LDSymbol* f_pStack;
+ LDSymbol* f_pDynamic;
+
+ // section symbols for .tdata and .tbss
+ LDSymbol* f_pTDATA;
+ LDSymbol* f_pTBSS;
// segment symbols
LDSymbol* f_pExecutableStart;
diff --git a/include/mcld/Target/GOT.h b/include/mcld/Target/GOT.h
index 5621778..6dfa9b1 100644
--- a/include/mcld/Target/GOT.h
+++ b/include/mcld/Target/GOT.h
@@ -13,49 +13,14 @@
#endif
#include <mcld/LD/LDSection.h>
-#include <mcld/LD/TargetFragment.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Fragment/TargetFragment.h>
-namespace mcld
-{
+namespace mcld {
class GOT;
+class LDSection;
class ResolveInfo;
-class SectionData;
-
-/** \class GOTEntry
- * \brief The entry of Global Offset Table
- */
-class GOTEntry : public TargetFragment
-{
-public:
- explicit GOTEntry(uint64_t pContent, size_t pEntrySize,
- SectionData* pParent);
-
- virtual ~GOTEntry();
-
- uint64_t& getContent()
- { return f_Content; }
-
- uint64_t getContent() const
- { return f_Content; }
-
- void setContent(uint64_t pValue)
- { f_Content = pValue; }
-
- static bool classof(const Fragment *pFrag)
- { return pFrag->getKind() == Fragment::Target; }
-
- static bool classof(const GOTEntry* pFrag)
- { return true; }
-
- // Override pure virtual function
- size_t getSize() const
- { return m_EntrySize; }
-
-protected:
- uint64_t f_Content;
- size_t m_EntrySize;
-};
/** \class GOT
* \brief The Global Offset Table
@@ -63,40 +28,70 @@
class GOT
{
protected:
- GOT(LDSection& pSection, SectionData& pSectionData, size_t pEntrySize);
+ GOT(LDSection& pSection, size_t pEntrySize);
+
+public:
+ typedef SectionData::iterator iterator;
+ typedef SectionData::const_iterator const_iterator;
+
+ class Entry : public TargetFragment
+ {
+ public:
+ Entry(uint64_t pContent, size_t pEntrySize, SectionData* pParent);
+
+ virtual ~Entry();
+
+ uint64_t getContent() const
+ { return f_Content; }
+
+ void setContent(uint64_t pValue)
+ { f_Content = pValue; }
+
+ // Override pure virtual function
+ size_t size() const
+ { return m_EntrySize; }
+
+ protected:
+ uint64_t f_Content;
+ size_t m_EntrySize;
+ };
public:
virtual ~GOT();
+ // ----- observers -----//
/// entrySize - the number of bytes per entry
size_t getEntrySize() const;
- const LDSection& getSection() const
- { return m_Section; }
+ uint64_t addr() const { return m_Section.addr(); }
- SectionData& getSectionData()
- { return m_SectionData; }
+ const_iterator begin() const { return m_SectionData->begin(); }
+ iterator begin() { return m_SectionData->begin(); }
+ const_iterator end () const { return m_SectionData->end(); }
+ iterator end () { return m_SectionData->end(); }
- const SectionData& getSectionData() const
- { return m_SectionData; }
+ bool empty() const
+ { return m_SectionData->empty(); }
-public:
- /// reserveEntry - reseve number of pNum of empty entries
+ // 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 reserveEntry(size_t pNum = 1) = 0;
+ virtual void reserve(size_t pNum = 1);
- /// getEntry - get an empty entry or an exitsted filled entry with pSymbol.
- /// @param pSymbol - the target symbol
- /// @param pExist - ture if a filled entry with pSymbol existed, otherwise false.
- virtual GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist) = 0;
+ /// consume - consume and return an empty entry
+ virtual Entry* consume();
protected:
LDSection& m_Section;
- SectionData& m_SectionData;
+ SectionData* m_SectionData;
size_t f_EntrySize;
+
+ Entry* m_pLast; ///< the last consumed entry
};
} // namespace of mcld
diff --git a/include/mcld/Target/OutputRelocSection.h b/include/mcld/Target/OutputRelocSection.h
index b75952b..ace0c71 100644
--- a/include/mcld/Target/OutputRelocSection.h
+++ b/include/mcld/Target/OutputRelocSection.h
@@ -12,15 +12,15 @@
#include <gtest.h>
#endif
-#include <llvm/ADT/DenseMap.h>
-#include <mcld/LD/SectionData.h>
-#include <mcld/LD/RelocationFactory.h>
+#include <mcld/LD/RelocData.h>
namespace mcld
{
-class ResolveInfo;
+class LDSymbol;
+class Module;
class Relocation;
+class RelocationFactory;
/** \class OutputRelocSection
* \brief Dynamic relocation section for ARM .rel.dyn and .rel.plt
@@ -28,31 +28,38 @@
class OutputRelocSection
{
public:
- OutputRelocSection(LDSection& pSection,
- SectionData& pSectionData,
+ OutputRelocSection(Module& pModule,
+ LDSection& pSection,
unsigned int pEntrySize);
~OutputRelocSection();
void reserveEntry(RelocationFactory& pRelFactory, size_t pNum=1);
- Relocation* getEntry(const ResolveInfo& pSymbol,
- bool isForGOT,
- bool& pExist);
+ Relocation* consumeEntry();
+
+ void finalizeSectionSize();
+
+ /// addSymbolToDynSym - add local symbol to TLS category so that it'll be
+ /// emitted into .dynsym
+ bool addSymbolToDynSym(LDSymbol& pSymbol);
+
+ // ----- observers ----- //
+ bool empty()
+ { return m_pRelocData->empty(); }
private:
- typedef llvm::DenseMap<const ResolveInfo*, Relocation*> SymRelMapType;
-
- typedef SymRelMapType::iterator SymRelMapIterator;
-
- typedef SectionData::iterator FragmentIterator;
+ typedef RelocData::iterator FragmentIterator;
private:
+ Module& m_Module;
+
/// m_pSection - LDSection of this Section
LDSection* m_pSection;
- /// m_SectionData - SectionData which contains the dynamic relocations
- SectionData* m_pSectionData;
+ /// m_RelocData - the output RelocData which contains the dynamic
+ /// relocations
+ RelocData* m_pRelocData;
/// m_EntryBytes - size of a relocation entry
unsigned int m_EntryBytes;
@@ -62,9 +69,6 @@
/// m_ValidEntryIterator - point to the first valid entry
FragmentIterator m_ValidEntryIterator;
-
- /// m_SymRelMap - map the resolved symbol to the Relocation entry
- SymRelMapType m_SymRelMap;
};
} // namespace of mcld
diff --git a/include/mcld/Target/PLT.h b/include/mcld/Target/PLT.h
index 2a4f641..bd5936a 100644
--- a/include/mcld/Target/PLT.h
+++ b/include/mcld/Target/PLT.h
@@ -12,74 +12,73 @@
#include <gtest.h>
#endif
-#include <llvm/ADT/ilist.h>
-
#include <mcld/LD/LDSection.h>
-#include <mcld/LD/TargetFragment.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Fragment/TargetFragment.h>
-namespace mcld
-{
+namespace mcld {
-class SectionData;
+class LDSection;
class ResolveInfo;
-/** \class PLTEntry
- */
-class PLTEntry : public TargetFragment
-{
-public:
- PLTEntry(size_t pSize, SectionData* pParent);
- virtual ~PLTEntry();
-
- size_t getEntrySize() const
- { return m_EntrySize; }
-
- void setContent(unsigned char* pContent)
- { m_pContent = pContent; }
-
- const unsigned char* getContent() const
- { return m_pContent; }
-
- //Used by llvm::cast<>.
- static bool classof(const Fragment *O)
- { return true; }
-
- size_t getSize() const
- { return m_EntrySize; }
-
-protected:
- size_t m_EntrySize;
- unsigned char* m_pContent;
-};
-
/** \class PLT
* \brief Procedure linkage table
*/
class PLT
{
public:
- PLT(LDSection& pSection, SectionData& pSectionData);
- virtual ~PLT();
+ typedef SectionData::iterator iterator;
+ typedef SectionData::const_iterator const_iterator;
- const LDSection& getSection() const
- { return m_Section; }
+ class Entry : public TargetFragment
+ {
+ public:
+ Entry(size_t pSize, SectionData& pParent);
+ virtual ~Entry();
- const SectionData& getSectionData() const
- { return m_SectionData; }
+ size_t getEntrySize() const
+ { return m_EntrySize; }
+
+ void setContent(unsigned char* pContent)
+ { m_pContent = pContent; }
+
+ const unsigned char* getContent() const
+ { return m_pContent; }
+
+ //Used by llvm::cast<>.
+ static bool classof(const Fragment *O)
+ { return true; }
+
+ size_t size() const
+ { return m_EntrySize; }
+
+ protected:
+ size_t m_EntrySize;
+ unsigned char* m_pContent;
+ };
public:
+ PLT(LDSection& pSection);
+
+ 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;
- /// getPLTEntry - get an empty entry or an exitsted filled entry with pSymbol.
- /// @param pSymbol - the target symbol
- /// @param pExist - ture if the a filled entry with pSymbol existed, otherwise false.
- virtual PLTEntry* getPLTEntry(const ResolveInfo& pSymbol, bool& pExist) = 0;
+ // finalizeSectionSize - set LDSection size
+ virtual void finalizeSectionSize() = 0;
+
+ uint64_t addr() const { return m_Section.addr(); }
+
+ const_iterator begin() const { return m_SectionData->begin(); }
+ iterator begin() { return m_SectionData->begin(); }
+ const_iterator end () const { return m_SectionData->end(); }
+ iterator end () { return m_SectionData->end(); }
protected:
LDSection& m_Section;
- SectionData& m_SectionData;
+ SectionData* m_SectionData;
};
} // namespace of mcld
diff --git a/include/mcld/Target/SymbolEntryMap.h b/include/mcld/Target/SymbolEntryMap.h
new file mode 100644
index 0000000..fc5ea93
--- /dev/null
+++ b/include/mcld/Target/SymbolEntryMap.h
@@ -0,0 +1,104 @@
+//===- 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 f4c02b5..c18bc79 100644
--- a/include/mcld/Target/TargetLDBackend.h
+++ b/include/mcld/Target/TargetLDBackend.h
@@ -6,16 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TARGET_TARGETLDBACKEND_H
-#define LLVM_TARGET_TARGETLDBACKEND_H
+#ifndef MCLD_TARGET_TARGETLDBACKEND_H
+#define MCLD_TARGET_TARGETLDBACKEND_H
#include <llvm/Support/DataTypes.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/LD/EhFrame.h>
namespace mcld {
-class MCLinker;
+class Module;
+class LinkerConfig;
+class FragmentLinker;
class Relocation;
class RelocationFactory;
class Layout;
@@ -25,38 +25,39 @@
class ObjectWriter;
class DynObjWriter;
class ExecWriter;
-class LDContext;
-class SectionMap;
-class Output;
-class MCLDInfo;
-class SymbolCategory;
-class Input;
class LDFileFormat;
+class LDSymbol;
+class LDSection;
+class SectionData;
+class Input;
class GOT;
+class MemoryArea;
class MemoryAreaFactory;
+class BranchIslandFactory;
+class StubFactory;
+class ObjectBuilder;
//===----------------------------------------------------------------------===//
/// TargetLDBackend - Generic interface to target specific assembler backends.
-///
+//===----------------------------------------------------------------------===//
class TargetLDBackend
{
TargetLDBackend(const TargetLDBackend &); // DO NOT IMPLEMENT
void operator=(const TargetLDBackend &); // DO NOT IMPLEMENT
protected:
- TargetLDBackend();
+ TargetLDBackend(const LinkerConfig& pConfig);
public:
virtual ~TargetLDBackend();
// ----- target dependent ----- //
- virtual bool initTargetSectionMap(SectionMap& pSectionMap) { return true;}
- virtual void initTargetSegments(MCLinker& pLinker) { }
- virtual void initTargetSections(MCLinker& pLinker) { }
- virtual void initTargetSymbols(MCLinker& pLinker, const Output& pOutput) { }
- virtual void initTargetRelocation(MCLinker& pLinker) { }
- virtual bool initStandardSymbols(MCLinker& pLinker, const Output& pOutput) = 0;
- virtual bool initRelocFactory(const MCLinker& pLinker) = 0;
+ virtual void initTargetSegments(FragmentLinker& pLinker) { }
+ virtual void initTargetSections(Module& pModule, ObjectBuilder& pBuilder) { }
+ virtual void initTargetSymbols(FragmentLinker& pLinker) { }
+ virtual void initTargetRelocation(FragmentLinker& pLinker) { }
+ virtual bool initStandardSymbols(FragmentLinker& pLinker, Module& pModule) = 0;
+ virtual bool initRelocFactory(const FragmentLinker& pLinker) = 0;
virtual RelocationFactory* getRelocFactory() = 0;
@@ -66,51 +67,42 @@
/// for layout to adjust the ouput offset.
/// @param pReloc - a read in relocation entry
/// @param pInputSym - the input LDSymbol of relocation target symbol
- /// @param pOutput - the ouput file
+ /// @param pSection - the section of relocation applying target
virtual void scanRelocation(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput,
+ FragmentLinker& pLinker,
+ Module& pModule,
const LDSection& pSection) = 0;
+ /// partialScanRelocation - When doing partial linking, backend can do any
+ /// modification to relocation to fix the relocation offset after section
+ /// merge
+ /// @param pReloc - a read in relocation entry
+ /// @param pInputSym - the input LDSymbol of relocation target symbol
+ /// @param pSection - the section of relocation applying target
+ virtual void partialScanRelocation(Relocation& pReloc,
+ FragmentLinker& pLinker,
+ Module& pModule,
+ const LDSection& pSection) = 0;
+
// ----- format dependent ----- //
- virtual bool initArchiveReader(MCLinker&,
- MCLDInfo&,
- MemoryAreaFactory&) = 0;
- virtual bool initObjectReader(MCLinker&) = 0;
- virtual bool initDynObjReader(MCLinker&) = 0;
- virtual bool initObjectWriter(MCLinker&) = 0;
- virtual bool initDynObjWriter(MCLinker&) = 0;
- virtual bool initExecWriter(MCLinker&) = 0;
+ virtual ArchiveReader* createArchiveReader(Module&) = 0;
+ virtual ObjectReader* createObjectReader(FragmentLinker&) = 0;
+ virtual DynObjReader* createDynObjReader(FragmentLinker&) = 0;
+ virtual ObjectWriter* createObjectWriter(FragmentLinker&) = 0;
+ virtual DynObjWriter* createDynObjWriter(FragmentLinker&) = 0;
+ virtual ExecWriter* createExecWriter(FragmentLinker&) = 0;
- virtual bool initExecSections(MCLinker&) = 0;
- virtual bool initDynObjSections(MCLinker&) = 0;
-
- virtual ArchiveReader *getArchiveReader() = 0;
- virtual ObjectReader *getObjectReader() = 0;
- virtual DynObjReader *getDynObjReader() = 0;
- virtual ObjectWriter *getObjectWriter() = 0;
- virtual DynObjWriter *getDynObjWriter() = 0;
- virtual ExecWriter *getExecWriter() = 0;
-
- virtual LDFileFormat* getDynObjFileFormat() = 0;
- virtual LDFileFormat* getExecFileFormat() = 0;
+ virtual bool initStdSections(ObjectBuilder& pBuilder) = 0;
/// preLayout - Backend can do any needed modification before layout
- virtual void preLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker) = 0;
+ virtual void preLayout(Module& pModule, FragmentLinker& pLinker) = 0;
/// postLayout -Backend can do any needed modification after layout
- virtual void postLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker) = 0;
+ virtual void postLayout(Module& pModule, FragmentLinker& pLinker) = 0;
/// postProcessing - Backend can do any needed modification in the final stage
- virtual void postProcessing(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker) = 0;
+ virtual void postProcessing(FragmentLinker& pLinker,
+ MemoryArea& pOutput) = 0;
/// Is the target machine little endian? **/
virtual bool isLittleEndian() const = 0;
@@ -119,41 +111,43 @@
virtual unsigned int bitclass() const = 0;
/// the common page size of the target machine
- virtual uint64_t commonPageSize(const MCLDInfo& pInfo) const = 0;
+ virtual uint64_t commonPageSize() const = 0;
/// the abi page size of the target machine
- virtual uint64_t abiPageSize(const MCLDInfo& pInfo) const = 0;
+ virtual uint64_t abiPageSize() const = 0;
/// section start offset in the output file
virtual size_t sectionStartOffset() const = 0;
/// computeSectionOrder - compute the layout order of the given section
- virtual unsigned int getSectionOrder(const Output& pOutput,
- const LDSection& pSectHdr,
- const MCLDInfo& pInfo) const = 0;
+ virtual unsigned int getSectionOrder(const LDSection& pSectHdr) const = 0;
/// sizeNamePools - compute the size of regular name pools
/// In ELF executable files, regular name pools are .symtab, .strtab.,
/// .dynsym, .dynstr, and .hash
virtual void
- sizeNamePools(const Output& pOutput,
- const SymbolCategory& pSymbols,
- const MCLDInfo& pLDInfo) = 0;
+ sizeNamePools(const Module& pModule, bool pIsStaticLink) = 0;
/// finalizeSymbol - Linker checks pSymbol.reserved() if it's not zero,
/// then it will ask backend to finalize the symbol value.
/// @return ture - if backend set the symbol value sucessfully
/// @return false - if backend do not recognize the symbol
- virtual bool finalizeSymbols(MCLinker& pLinker, const Output& pOutput) = 0;
+ virtual bool finalizeSymbols(FragmentLinker& pLinker) = 0;
+
+ /// finalizeTLSSymbol - Linker asks backend to set the symbol value when it
+ /// meets a TLS symbol
+ virtual bool finalizeTLSSymbol(LDSymbol& pSymbol) = 0;
/// allocateCommonSymbols - allocate common symbols in the corresponding
/// sections.
- virtual bool allocateCommonSymbols(const MCLDInfo& pLDInfo, MCLinker& pLinker) const = 0;
+ virtual bool allocateCommonSymbols(Module& pModule) = 0;
+
+ /// mergeSection - merge target dependent sections.
+ virtual bool mergeSection(Module& pModule, LDSection& pInputSection)
+ { return true; }
/// readSection - read a target dependent section
- virtual bool readSection(Input& pInput,
- MCLinker& pLinker,
- LDSection& pInputSectHdr)
+ virtual bool readSection(Input& pInput, SectionData& pSD)
{ return true; }
/// dyld - the name of the default dynamic linker
@@ -161,17 +155,27 @@
/// 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(const Output& pOutput, const MCLDInfo& pLDInfo) = 0;
+ virtual void sizeInterp() = 0;
-public:
- EhFrame* getEhFrame();
+ // ----- relaxation ----- //
+ virtual bool initBRIslandFactory() = 0;
+ virtual bool initStubFactory() = 0;
+ virtual bool initTargetStubs(FragmentLinker& pLinker) { return true; }
- const EhFrame* getEhFrame() const;
+ virtual BranchIslandFactory* getBRIslandFactory() = 0;
+ virtual StubFactory* getStubFactory() = 0;
+
+ /// relax - the relaxation pass
+ virtual bool relax(Module& pModule, FragmentLinker& pLinker) = 0;
+
+ /// mayRelax - return true if the backend needs to do relaxation
+ virtual bool mayRelax() = 0;
+
+protected:
+ const LinkerConfig& config() const { return m_Config; }
private:
- /// m_pEhFrame - section .eh_frame
- EhFrame* m_pEhFrame;
-
+ const LinkerConfig& m_Config;
};
} // End mcld namespace
diff --git a/include/mcld/Target/TargetMachine.h b/include/mcld/Target/TargetMachine.h
index 02df7fd..1b167ab 100644
--- a/include/mcld/Target/TargetMachine.h
+++ b/include/mcld/Target/TargetMachine.h
@@ -6,31 +6,31 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef MCLD_TARGET_MACHINE_H
-#define MCLD_TARGET_MACHINE_H
+#ifndef MCLD_TARGET_TARGET_MACHINE_H
+#define MCLD_TARGET_TARGET_MACHINE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <llvm/Target/TargetMachine.h>
#include <string>
-#include "mcld/MC/MCLDFile.h"
-namespace llvm
-{
+namespace llvm {
+
class Target;
class TargetData;
class TargetMachine;
class PassManagerBase;
-class formatted_raw_ostream;
} // namespace of llvm
-namespace mcld
-{
+namespace mcld {
+class Module;
class Target;
-class MCLDInfo;
-class SectLinkerOption;
+class MemoryArea;
+class LinkerConfig;
+class ToolOutputFile;
+
using namespace llvm;
enum CodeGenFileType {
@@ -38,47 +38,40 @@
CGFT_OBJFile,
CGFT_DSOFile,
CGFT_EXEFile,
+ CGFT_PARTIAL,
CGFT_NULLFile
};
-/** \class mcld::LLVMTargetMachine
- * \brief mcld::LLVMTargetMachine is a object adapter of
- * llvm::LLVMTargetMachine.
- *
- * mcld::LLVMTargetMachine is also in charge of MCLDInfo.
- *
- * @see MCLDInfo
+/** \class mcld::MCLDTargetMachine
+ * \brief mcld::MCLDTargetMachine is a object adapter of LLVMTargetMachine.
*/
-class LLVMTargetMachine
+class MCLDTargetMachine
{
public:
/// Adapter of llvm::TargetMachine
///
- LLVMTargetMachine(llvm::TargetMachine &pTM,
+ MCLDTargetMachine(llvm::TargetMachine &pTM,
const mcld::Target &pTarget,
const std::string &pTriple);
- virtual ~LLVMTargetMachine();
+
+ virtual ~MCLDTargetMachine();
/// getTarget - adapt llvm::TargetMachine::getTarget
const mcld::Target& getTarget() const;
/// getTM - return adapted the llvm::TargetMachine.
const llvm::TargetMachine& getTM() const { return m_TM; }
- llvm::TargetMachine& getTM() { return m_TM; }
-
- /// getLDInfo - return the mcld::MCLDInfo
- virtual mcld::MCLDInfo& getLDInfo() = 0;
- virtual const mcld::MCLDInfo& getLDInfo() const = 0;
+ llvm::TargetMachine& getTM() { return m_TM; }
/// appPassesToEmitFile - The target function which we has to modify as
/// upstreaming.
bool addPassesToEmitFile(PassManagerBase &,
- formatted_raw_ostream &Out,
- const std::string &pOutputFilename,
+ mcld::ToolOutputFile& pOutput,
mcld::CodeGenFileType,
CodeGenOpt::Level,
- SectLinkerOption *pLinkerOpt = NULL,
+ mcld::Module& pModule,
+ mcld::LinkerConfig& pConfig,
bool DisableVerify = true);
/// getTargetData
@@ -98,20 +91,18 @@
bool DisableVerify,
llvm::MCContext *&OutCtx);
- bool addCompilerPasses(PassManagerBase &,
- formatted_raw_ostream &Out,
- const std::string& pOutputFilename,
+ bool addCompilerPasses(PassManagerBase &pPM,
+ llvm::formatted_raw_ostream &pOutput,
llvm::MCContext *&OutCtx);
- bool addAssemblerPasses(PassManagerBase &,
- formatted_raw_ostream &Out,
- const std::string& pOutputFilename,
+ bool addAssemblerPasses(PassManagerBase &pPM,
+ llvm::raw_ostream &pOutput,
llvm::MCContext *&OutCtx);
- bool addLinkerPasses(PassManagerBase &,
- SectLinkerOption *pLinkerOpt,
- const std::string& pOutputFilename,
- MCLDFile::Type pOutputLinkType,
+ bool addLinkerPasses(PassManagerBase &pPM,
+ LinkerConfig& pConfig,
+ Module& pModule,
+ mcld::MemoryArea& pOutput,
llvm::MCContext *&OutCtx);
private:
diff --git a/lib/CodeGen/Android.mk b/lib/CodeGen/Android.mk
index 8754d65..9954552 100644
--- a/lib/CodeGen/Android.mk
+++ b/lib/CodeGen/Android.mk
@@ -1,9 +1,8 @@
LOCAL_PATH:= $(call my-dir)
mcld_codegen_SRC_FILES := \
- LLVMTargetMachine.cpp \
- SectLinker.cpp \
- SectLinkerOption.cpp
+ MCLDTargetMachine.cpp \
+ MCLinker.cpp
# For the host
# =====================================================
diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/MCLDTargetMachine.cpp
similarity index 79%
rename from lib/CodeGen/LLVMTargetMachine.cpp
rename to lib/CodeGen/MCLDTargetMachine.cpp
index 822ff36..e0eeb63 100644
--- a/lib/CodeGen/LLVMTargetMachine.cpp
+++ b/lib/CodeGen/MCLDTargetMachine.cpp
@@ -1,4 +1,4 @@
-//===- LLVMTargetMachine.cpp ----------------------------------------------===//
+//===- MCLDTargetMachine.cpp ----------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,13 +6,15 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
-#include <mcld/CodeGen/SectLinker.h>
-#include <mcld/CodeGen/SectLinkerOption.h>
-#include <mcld/MC/MCLDFile.h>
-#include <mcld/Support/RealPath.h>
-#include <mcld/Support/TargetRegistry.h>
#include <mcld/Target/TargetMachine.h>
+
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/CodeGen/MCLinker.h>
+#include <mcld/Support/raw_mem_ostream.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/Support/ToolOutputFile.h>
+#include <mcld/Support/MemoryArea.h>
#include <mcld/Target/TargetLDBackend.h>
#include <llvm/ADT/OwningPtr.h>
@@ -37,7 +39,6 @@
#include <llvm/Support/Debug.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/FormattedStream.h>
-#include <llvm/Support/ToolOutputFile.h>
#include <llvm/Target/TargetData.h>
#include <llvm/Target/TargetInstrInfo.h>
#include <llvm/Target/TargetLowering.h>
@@ -90,19 +91,19 @@
//===---------------------------------------------------------------------===//
-/// LLVMTargetMachine
+/// MCLDTargetMachine
//===----------------------------------------------------------------------===//
-mcld::LLVMTargetMachine::LLVMTargetMachine(llvm::TargetMachine &pTM,
+mcld::MCLDTargetMachine::MCLDTargetMachine(llvm::TargetMachine &pTM,
const mcld::Target& pTarget,
- const std::string& pTriple )
+ const std::string& pTriple)
: m_TM(pTM), m_pTarget(&pTarget), m_Triple(pTriple) {
}
-mcld::LLVMTargetMachine::~LLVMTargetMachine() {
+mcld::MCLDTargetMachine::~MCLDTargetMachine() {
m_pTarget = 0;
}
-const mcld::Target& mcld::LLVMTargetMachine::getTarget() const
+const mcld::Target& mcld::MCLDTargetMachine::getTarget() const
{
return *m_pTarget;
}
@@ -137,8 +138,8 @@
static llvm::MCContext *addPassesToGenerateCode(llvm::LLVMTargetMachine *TM,
- PassManagerBase &PM,
- bool DisableVerify)
+ PassManagerBase &PM,
+ bool DisableVerify)
{
// Targets may override createPassConfig to provide a target-specific sublass.
TargetPassConfig *PassConfig = TM->createPassConfig(PM);
@@ -183,12 +184,12 @@
}
-bool mcld::LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &pPM,
- formatted_raw_ostream &Out,
- const std::string& pOutputFilename,
+bool mcld::MCLDTargetMachine::addPassesToEmitFile(PassManagerBase &pPM,
+ mcld::ToolOutputFile& pOutput,
mcld::CodeGenFileType pFileType,
CodeGenOpt::Level pOptLvl,
- SectLinkerOption *pLinkerOpt,
+ mcld::Module& pModule,
+ LinkerConfig& pConfig,
bool pDisableVerify)
{
@@ -210,8 +211,7 @@
Context->setAllowTemporaryLabels(false);
if (addCompilerPasses(pPM,
- Out,
- pOutputFilename,
+ pOutput.formatted_os(),
Context))
return true;
@@ -224,8 +224,7 @@
if (getTM().hasMCSaveTempLabels())
Context->setAllowTemporaryLabels(false);
if (addAssemblerPasses(pPM,
- Out,
- pOutputFilename,
+ pOutput.mem_os(),
Context))
return true;
@@ -233,25 +232,31 @@
break;
}
case CGFT_EXEFile: {
- if (pLinkerOpt == NULL)
- return true;
-
+ pConfig.setCodeGenType(LinkerConfig::Exec);
if (addLinkerPasses(pPM,
- pLinkerOpt,
- pOutputFilename,
- MCLDFile::Exec,
+ pConfig,
+ pModule,
+ pOutput.memory(),
Context))
return true;
break;
}
case CGFT_DSOFile: {
- if (pLinkerOpt == NULL)
- return true;
-
+ pConfig.setCodeGenType(LinkerConfig::DynObj);
if (addLinkerPasses(pPM,
- pLinkerOpt,
- pOutputFilename,
- MCLDFile::DynObj,
+ pConfig,
+ pModule,
+ pOutput.memory(),
+ Context))
+ return true;
+ break;
+ }
+ case CGFT_PARTIAL: {
+ pConfig.setCodeGenType(LinkerConfig::Object);
+ if (addLinkerPasses(pPM,
+ pConfig,
+ pModule,
+ pOutput.memory(),
Context))
return true;
break;
@@ -260,9 +265,8 @@
return false;
}
-bool mcld::LLVMTargetMachine::addCompilerPasses(PassManagerBase &pPM,
- formatted_raw_ostream &Out,
- const std::string& pOutputFilename,
+bool mcld::MCLDTargetMachine::addCompilerPasses(PassManagerBase &pPM,
+ llvm::formatted_raw_ostream &pOutput,
llvm::MCContext *&Context)
{
const MCAsmInfo &MAI = *getTM().getMCAsmInfo();
@@ -285,7 +289,7 @@
// now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer.
OwningPtr<MCStreamer> AsmStreamer(
- getTarget().get()->createAsmStreamer(*Context, Out,
+ getTarget().get()->createAsmStreamer(*Context, pOutput,
getVerboseAsm(),
getTM().hasMCUseLoc(),
getTM().hasMCUseCFI(),
@@ -305,9 +309,8 @@
return false;
}
-bool mcld::LLVMTargetMachine::addAssemblerPasses(PassManagerBase &pPM,
- formatted_raw_ostream &Out,
- const std::string& pOutputFilename,
+bool mcld::MCLDTargetMachine::addAssemblerPasses(PassManagerBase &pPM,
+ llvm::raw_ostream &pOutput,
llvm::MCContext *&Context)
{
// MCCodeEmitter
@@ -327,7 +330,7 @@
m_Triple,
*Context,
*MAB,
- Out,
+ pOutput,
MCE,
getTM().hasMCRelaxAll(),
getTM().hasMCNoExecStack()));
@@ -342,31 +345,30 @@
return false;
}
-bool mcld::LLVMTargetMachine::addLinkerPasses(PassManagerBase &pPM,
- SectLinkerOption *pLinkerOpt,
- const std::string &pOutputFilename,
- MCLDFile::Type pOutputLinkType,
+bool mcld::MCLDTargetMachine::addLinkerPasses(PassManagerBase &pPM,
+ LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ mcld::MemoryArea& pOutput,
llvm::MCContext *&Context)
{
- TargetLDBackend* ldBackend = getTarget().createLDBackend(m_Triple);
- if (0 == ldBackend)
+ if (NULL == pOutput.handler())
return true;
// set up output's SOName
- if (pOutputLinkType == MCLDFile::DynObj &&
- pLinkerOpt->info().output().name().empty()) {
+ if (pConfig.options().soname().empty()) {
// if the output is a shared object, and the option -soname was not
// enable, set soname as the output file name.
- pLinkerOpt->info().output().setSOName(pOutputFilename);
+ pModule.setName(pOutput.handler()->path().native());
+ }
+ else {
+ pModule.setName(pConfig.options().soname());
}
- pLinkerOpt->info().output().setPath(sys::fs::RealPath(pOutputFilename));
- pLinkerOpt->info().output().setType(pOutputLinkType);
-
- MachineFunctionPass* funcPass = getTarget().createSectLinker(m_Triple,
- *pLinkerOpt,
- *ldBackend);
- if (0 == funcPass)
+ MachineFunctionPass* funcPass = getTarget().createMCLinker(m_Triple,
+ pConfig,
+ pModule,
+ pOutput);
+ if (NULL == funcPass)
return true;
pPM.add(funcPass);
diff --git a/lib/CodeGen/MCLinker.cpp b/lib/CodeGen/MCLinker.cpp
new file mode 100644
index 0000000..bce4689
--- /dev/null
+++ b/lib/CodeGen/MCLinker.cpp
@@ -0,0 +1,390 @@
+//===- MCLinker.cpp -------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the MCLinker class.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/CodeGen/MCLinker.h>
+
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/InputTree.h>
+#include <mcld/Linker.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/FileAction.h>
+#include <mcld/MC/CommandAction.h>
+#include <mcld/Object/ObjectLinker.h>
+#include <mcld/Support/CommandLine.h>
+#include <mcld/Support/FileSystem.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/Support/MemoryArea.h>
+
+#include <llvm/Module.h>
+#include <llvm/Support/CommandLine.h>
+
+#include <algorithm>
+#include <vector>
+#include <string>
+
+using namespace mcld;
+using namespace llvm;
+
+char MCLinker::m_ID = 0;
+
+//===----------------------------------------------------------------------===//
+// Help Functions
+//===----------------------------------------------------------------------===//
+static inline bool CompareAction(const InputAction* X, const InputAction* Y)
+{
+ return (X->position() < Y->position());
+}
+
+//===----------------------------------------------------------------------===//
+// Positional Options
+// There are four kinds of positional options:
+// 1. Inputs, object files, such as /tmp/XXXX.o
+// 2. Namespecs, short names of libraries. A namespec may refer to an archive
+// or a shared library. For example, -lm.
+// 3. Attributes of inputs. Attributes describe inputs appears after them.
+// For example, --as-needed and --whole-archive.
+// 4. Groups. A Group is a set of archives. Linkers repeatedly read archives
+// in groups until there is no new undefined symbols.
+// 5. Bitcode. Bitcode is a kind of object files. MCLinker compiles it to
+// object file first, then link it as a object file. (Bitcode is recorded
+// in BitcodeOption, not be read by LLVM Command Line library.)
+//===----------------------------------------------------------------------===//
+// Inputs
+//===----------------------------------------------------------------------===//
+static cl::list<mcld::sys::fs::Path>
+ArgInputObjectFiles(cl::Positional,
+ cl::desc("[input object files]"),
+ cl::ZeroOrMore);
+
+//===----------------------------------------------------------------------===//
+// Namespecs
+//===----------------------------------------------------------------------===//
+static cl::list<std::string>
+ArgNameSpecList("l",
+ cl::ZeroOrMore,
+ cl::desc("Add the archive or object file specified by namespec to "
+ "the list of files to link."),
+ cl::value_desc("namespec"),
+ cl::Prefix);
+
+static cl::alias
+ArgNameSpecListAlias("library",
+ cl::desc("alias for -l"),
+ cl::aliasopt(ArgNameSpecList));
+
+//===----------------------------------------------------------------------===//
+// Attributes
+//===----------------------------------------------------------------------===//
+static cl::list<bool>
+ArgWholeArchiveList("whole-archive",
+ cl::ValueDisallowed,
+ cl::desc("For each archive mentioned on the command line after "
+ "the --whole-archive option, include all object files "
+ "in the archive."));
+
+static cl::list<bool>
+ArgNoWholeArchiveList("no-whole-archive",
+ cl::ValueDisallowed,
+ cl::desc("Turn off the effect of the --whole-archive option for "
+ "subsequent archive files."));
+
+static cl::list<bool>
+ArgAsNeededList("as-needed",
+ cl::ValueDisallowed,
+ cl::desc("This option affects ELF DT_NEEDED tags for dynamic "
+ "libraries mentioned on the command line after the "
+ "--as-needed option."));
+
+static cl::list<bool>
+ArgNoAsNeededList("no-as-needed",
+ cl::ValueDisallowed,
+ cl::desc("Turn off the effect of the --as-needed option for "
+ "subsequent dynamic libraries"));
+
+static cl::list<bool>
+ArgAddNeededList("add-needed",
+ cl::ValueDisallowed,
+ cl::desc("--add-needed causes DT_NEEDED tags are always "
+ "emitted for those libraries from DT_NEEDED tags. "
+ "This is the default behavior."));
+
+static cl::list<bool>
+ArgNoAddNeededList("no-add-needed",
+ cl::ValueDisallowed,
+ cl::desc("--no-add-needed causes DT_NEEDED tags will never be "
+ "emitted for those libraries from DT_NEEDED tags"));
+
+static cl::list<bool>
+ArgBDynamicList("Bdynamic",
+ cl::ValueDisallowed,
+ cl::desc("Link against dynamic library"));
+
+static cl::alias
+ArgBDynamicListAlias1("dy",
+ cl::desc("alias for --Bdynamic"),
+ cl::aliasopt(ArgBDynamicList));
+
+static cl::alias
+ArgBDynamicListAlias2("call_shared",
+ cl::desc("alias for --Bdynamic"),
+ cl::aliasopt(ArgBDynamicList));
+
+static cl::list<bool>
+ArgBStaticList("Bstatic",
+ cl::ValueDisallowed,
+ cl::desc("Link against static library"));
+
+static cl::alias
+ArgBStaticListAlias1("dn",
+ cl::desc("alias for --Bstatic"),
+ cl::aliasopt(ArgBStaticList));
+
+static cl::alias
+ArgBStaticListAlias2("static",
+ cl::desc("alias for --Bstatic"),
+ cl::aliasopt(ArgBStaticList));
+
+static cl::alias
+ArgBStaticListAlias3("non_shared",
+ cl::desc("alias for --Bstatic"),
+ cl::aliasopt(ArgBStaticList));
+
+//===----------------------------------------------------------------------===//
+// Groups
+//===----------------------------------------------------------------------===//
+static cl::list<bool>
+ArgStartGroupList("start-group",
+ cl::ValueDisallowed,
+ cl::desc("start to record a group of archives"));
+
+static cl::alias
+ArgStartGroupListAlias("(",
+ cl::desc("alias for --start-group"),
+ cl::aliasopt(ArgStartGroupList));
+
+static cl::list<bool>
+ArgEndGroupList("end-group",
+ cl::ValueDisallowed,
+ cl::desc("stop recording a group of archives"));
+
+static cl::alias
+ArgEndGroupListAlias(")",
+ cl::desc("alias for --end-group"),
+ cl::aliasopt(ArgEndGroupList));
+
+//===----------------------------------------------------------------------===//
+// MCLinker
+//===----------------------------------------------------------------------===//
+MCLinker::MCLinker(LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ MemoryArea& pOutput)
+ : MachineFunctionPass(m_ID),
+ m_Config(pConfig),
+ m_Module(pModule),
+ m_Output(pOutput),
+ m_pBuilder(NULL),
+ m_pLinker(NULL) {
+}
+
+MCLinker::~MCLinker()
+{
+ delete m_pLinker;
+ delete m_pBuilder;
+}
+
+bool MCLinker::doInitialization(llvm::Module &pM)
+{
+ // Now, all input arguments are prepared well, send it into ObjectLinker
+ m_pLinker = new Linker();
+
+ if (!m_pLinker->config(m_Config))
+ return false;
+
+ m_pBuilder = new IRBuilder(m_Module, m_Config);
+
+ initializeInputTree(*m_pBuilder);
+
+ return true;
+}
+
+bool MCLinker::doFinalization(llvm::Module &pM)
+{
+ if (!m_pLinker->link(m_Module, *m_pBuilder))
+ return true;
+
+ if (!m_pLinker->emit(m_Output))
+ return true;
+
+ return false;
+}
+
+bool MCLinker::runOnMachineFunction(MachineFunction& pF)
+{
+ // basically, linkers do nothing during function is generated.
+ return false;
+}
+
+void MCLinker::initializeInputTree(IRBuilder& pBuilder)
+{
+ if (0 == ArgInputObjectFiles.size() &&
+ 0 == ArgNameSpecList.size() &&
+ !m_Config.bitcode().hasDefined()) {
+ fatal(diag::err_no_inputs);
+ return;
+ }
+
+ size_t num_actions = ArgInputObjectFiles.size() +
+ ArgNameSpecList.size() +
+ ArgWholeArchiveList.size() +
+ ArgNoWholeArchiveList.size() +
+ ArgAsNeededList.size() +
+ ArgNoAsNeededList.size() +
+ ArgAddNeededList.size() +
+ ArgNoAddNeededList.size() +
+ ArgBDynamicList.size() +
+ ArgBStaticList.size() +
+ ArgStartGroupList.size() +
+ ArgEndGroupList.size() +
+ 1; // bitcode
+ std::vector<InputAction*> actions;
+ actions.reserve(num_actions);
+
+ // ----- inputs ----- //
+ cl::list<mcld::sys::fs::Path>::iterator input, inBegin, inEnd;
+ inBegin = ArgInputObjectFiles.begin();
+ inEnd = ArgInputObjectFiles.end();
+ for (input = inBegin; input != inEnd; ++input) {
+ unsigned int pos = ArgInputObjectFiles.getPosition(input - inBegin);
+ actions.push_back(new InputFileAction(pos, *input));
+ actions.push_back(new ContextAction(pos));
+ actions.push_back(new MemoryAreaAction(pos, FileHandle::ReadOnly));
+ }
+
+ // ----- namespecs ----- //
+ cl::list<std::string>::iterator namespec, nsBegin, nsEnd;
+ nsBegin = ArgNameSpecList.begin();
+ nsEnd = ArgNameSpecList.end();
+ for (namespec = nsBegin; namespec != nsEnd; ++namespec) {
+ unsigned int pos = ArgNameSpecList.getPosition(namespec - nsBegin);
+ actions.push_back(new NamespecAction(pos, *namespec,
+ m_Config.options().directories()));
+ actions.push_back(new ContextAction(pos));
+ actions.push_back(new MemoryAreaAction(pos, FileHandle::ReadOnly));
+ }
+
+ // ----- attributes ----- //
+ /// --whole-archive
+ cl::list<bool>::iterator attr, attrBegin, attrEnd;
+ attrBegin = ArgWholeArchiveList.begin();
+ attrEnd = ArgWholeArchiveList.end();
+ for (attr = attrBegin; attr != attrEnd; ++attr) {
+ unsigned int pos = ArgWholeArchiveList.getPosition(attr - attrBegin);
+ actions.push_back(new WholeArchiveAction(pos));
+ }
+
+ /// --no-whole-archive
+ attrBegin = ArgNoWholeArchiveList.begin();
+ attrEnd = ArgNoWholeArchiveList.end();
+ for (attr = attrBegin; attr != attrEnd; ++attr) {
+ unsigned int pos = ArgNoWholeArchiveList.getPosition(attr - attrBegin);
+ actions.push_back(new NoWholeArchiveAction(pos));
+ }
+
+ /// --as-needed
+ attrBegin = ArgAsNeededList.begin();
+ attrEnd = ArgAsNeededList.end();
+ for (attr = attrBegin; attr != attrEnd; ++attr) {
+ unsigned int pos = ArgAsNeededList.getPosition(attr - attrBegin);
+ actions.push_back(new AsNeededAction(pos));
+ }
+
+ /// --no-as-needed
+ attrBegin = ArgNoAsNeededList.begin();
+ attrEnd = ArgNoAsNeededList.end();
+ for (attr = attrBegin; attr != attrEnd; ++attr) {
+ unsigned int pos = ArgNoAsNeededList.getPosition(attr - attrBegin);
+ actions.push_back(new NoAsNeededAction(pos));
+ }
+
+ /// --add--needed
+ attrBegin = ArgAddNeededList.begin();
+ attrEnd = ArgAddNeededList.end();
+ for (attr = attrBegin; attr != attrEnd; ++attr) {
+ unsigned int pos = ArgAddNeededList.getPosition(attr - attrBegin);
+ actions.push_back(new AddNeededAction(pos));
+ }
+
+ /// --no-add--needed
+ attrBegin = ArgNoAddNeededList.begin();
+ attrEnd = ArgNoAddNeededList.end();
+ for (attr = attrBegin; attr != attrEnd; ++attr) {
+ unsigned int pos = ArgNoAddNeededList.getPosition(attr - attrBegin);
+ actions.push_back(new NoAddNeededAction(pos));
+ }
+
+ /// --Bdynamic
+ attrBegin = ArgBDynamicList.begin();
+ attrEnd = ArgBDynamicList.end();
+ for (attr = attrBegin; attr != attrEnd; ++attr) {
+ unsigned int pos = ArgBDynamicList.getPosition(attr - attrBegin);
+ actions.push_back(new BDynamicAction(pos));
+ }
+
+ /// --Bstatic
+ attrBegin = ArgBStaticList.begin();
+ attrEnd = ArgBStaticList.end();
+ for (attr = attrBegin; attr != attrEnd; ++attr) {
+ unsigned int pos = ArgBStaticList.getPosition(attr - attrBegin);
+ actions.push_back(new BStaticAction(pos));
+ }
+
+ // ----- groups ----- //
+ /// --start-group
+ cl::list<bool>::iterator group, gsBegin, gsEnd;
+ gsBegin = ArgStartGroupList.begin();
+ gsEnd = ArgStartGroupList.end();
+ for (group = gsBegin; group != gsEnd; ++group) {
+ unsigned int pos = ArgStartGroupList.getPosition(group - gsBegin);
+ actions.push_back(new StartGroupAction(pos));
+ }
+
+ /// --end-group
+ gsBegin = ArgEndGroupList.begin();
+ gsEnd = ArgEndGroupList.end();
+ for (group = gsBegin; group != gsEnd; ++group) {
+ unsigned int pos = ArgEndGroupList.getPosition(group - gsBegin);
+ actions.push_back(new EndGroupAction(pos));
+ }
+
+ // ----- bitcode ----- //
+ if (m_Config.bitcode().hasDefined()) {
+ actions.push_back(new BitcodeAction(m_Config.bitcode().getPosition(),
+ m_Config.bitcode().getPath()));
+ }
+
+ // stable sort
+ std::stable_sort(actions.begin(), actions.end(), CompareAction);
+
+ // build up input tree
+ std::vector<InputAction*>::iterator action, actionEnd = actions.end();
+ for (action = actions.begin(); action != actionEnd; ++action) {
+ (*action)->activate(pBuilder.getInputBuilder());
+ }
+
+ if (pBuilder.getInputBuilder().isInGroup())
+ report_fatal_error("no matched --start-group and --end-group");
+}
+
diff --git a/lib/CodeGen/SectLinker.cpp b/lib/CodeGen/SectLinker.cpp
deleted file mode 100644
index 0e4c3ad..0000000
--- a/lib/CodeGen/SectLinker.cpp
+++ /dev/null
@@ -1,404 +0,0 @@
-//===- SectLinker.cpp -----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the SectLinker class.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Support/FileHandle.h>
-#include <mcld/MC/InputTree.h>
-#include <mcld/MC/MCLDDriver.h>
-#include <mcld/Support/FileSystem.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/raw_ostream.h>
-#include <mcld/Support/MemoryAreaFactory.h>
-#include <mcld/Support/DerivedPositionDependentOptions.h>
-#include <mcld/Target/TargetLDBackend.h>
-#include <mcld/CodeGen/SectLinker.h>
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-#include <llvm/Module.h>
-
-#include <algorithm>
-#include <stack>
-#include <string>
-
-using namespace mcld;
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Forward declarations
-char SectLinker::m_ID = 0;
-static bool CompareOption(const PositionDependentOption* X,
- const PositionDependentOption* Y);
-
-//===----------------------------------------------------------------------===//
-// SectLinker
-SectLinker::SectLinker(SectLinkerOption &pOption,
- TargetLDBackend& pLDBackend)
- : MachineFunctionPass(m_ID),
- m_pOption(&pOption),
- m_pLDBackend(&pLDBackend),
- m_pLDDriver(NULL),
- m_pMemAreaFactory(NULL)
-{
- m_pMemAreaFactory = new MemoryAreaFactory(32);
-}
-
-SectLinker::~SectLinker()
-{
- delete m_pLDDriver;
-
- // FIXME: current implementation can not change the order of delete.
- //
- // Instance of TargetLDBackend was created outside and is not managed by
- // SectLinker. It should not be destroyed here and by SectLinker. However, in
- // order to follow the LLVM convention - that is, the pass manages all the
- // objects it used during the processing, we destroy the object of
- // TargetLDBackend here.
- delete m_pLDBackend;
-
- delete m_pMemAreaFactory;
-}
-
-bool SectLinker::doInitialization(Module &pM)
-{
- MCLDInfo &info = m_pOption->info();
-
- // ----- convert position dependent options into tree of input files ----- //
- PositionDependentOptions &PosDepOpts = m_pOption->pos_dep_options();
- std::stable_sort(PosDepOpts.begin(), PosDepOpts.end(), CompareOption);
- initializeInputTree(PosDepOpts);
- initializeInputOutput(info);
- // Now, all input arguments are prepared well, send it into MCLDDriver
- m_pLDDriver = new MCLDDriver(info, *m_pLDBackend, *memAreaFactory());
-
- return false;
-}
-
-bool SectLinker::doFinalization(Module &pM)
-{
- const MCLDInfo &info = m_pOption->info();
-
- // 2. - initialize MCLinker
- if (!m_pLDDriver->initMCLinker())
- return true;
-
- // 3. - initialize output's standard sections
- if (!m_pLDDriver->initStdSections())
- return true;
-
- // 4. - normalize the input tree
- m_pLDDriver->normalize();
-
- if (info.options().trace()) {
- static int counter = 0;
- mcld::outs() << "** name\ttype\tpath\tsize (" << info.inputs().size() << ")\n";
- InputTree::const_dfs_iterator input, inEnd = info.inputs().dfs_end();
- for (input=info.inputs().dfs_begin(); input!=inEnd; ++input) {
- mcld::outs() << counter++ << " * " << (*input)->name();
- switch((*input)->type()) {
- case Input::Archive:
- mcld::outs() << "\tarchive\t(";
- break;
- case Input::Object:
- mcld::outs() << "\tobject\t(";
- break;
- case Input::DynObj:
- mcld::outs() << "\tshared\t(";
- break;
- case Input::Script:
- mcld::outs() << "\tscript\t(";
- break;
- case Input::External:
- mcld::outs() << "\textern\t(";
- break;
- default:
- unreachable(diag::err_cannot_trace_file) << (*input)->type()
- << (*input)->name()
- << (*input)->path();
- }
- mcld::outs() << (*input)->path() << ")\n";
- }
- }
-
- // 5. - check if we can do static linking and if we use split-stack.
- if (!m_pLDDriver->linkable())
- return true;
-
-
- // 6. - merge all sections
- if (!m_pLDDriver->mergeSections())
- return true;
-
- // 7. - add standard symbols and target-dependent symbols
- // m_pLDDriver->addUndefSymbols();
- if (!m_pLDDriver->addStandardSymbols() ||
- !m_pLDDriver->addTargetSymbols())
- return true;
-
- // 8. - read all relocation entries from input files
- m_pLDDriver->readRelocations();
-
- // 9. - pre-layout
- m_pLDDriver->prelayout();
-
- // 10. - linear layout
- m_pLDDriver->layout();
-
- // 10.b - post-layout (create segment, instruction relaxing)
- m_pLDDriver->postlayout();
-
- // 11. - finalize symbol value
- m_pLDDriver->finalizeSymbolValue();
-
- // 12. - apply relocations
- m_pLDDriver->relocation();
-
- // 13. - write out output
- m_pLDDriver->emitOutput();
-
- // 14. - post processing
- m_pLDDriver->postProcessing();
- return false;
-}
-
-bool SectLinker::runOnMachineFunction(MachineFunction& pF)
-{
- // basically, linkers do nothing during function is generated.
- return false;
-}
-
-void SectLinker::initializeInputOutput(MCLDInfo &pLDInfo)
-{
- // ----- initialize output file ----- //
- FileHandle::Permission perm;
- if (Output::Object == pLDInfo.output().type())
- perm = 0544;
- else
- perm = 0755;
-
- MemoryArea* out_area = memAreaFactory()->produce(pLDInfo.output().path(),
- FileHandle::ReadWrite,
- perm);
-
- if (!out_area->handler()->isGood()) {
- // make sure output is openend successfully.
- fatal(diag::err_cannot_open_output_file) << pLDInfo.output().name()
- << pLDInfo.output().path();
- }
-
- pLDInfo.output().setMemArea(out_area);
- pLDInfo.output().setContext(pLDInfo.contextFactory().produce());
-
- // ----- initialize input files ----- //
- InputTree::dfs_iterator input, inEnd = pLDInfo.inputs().dfs_end();
- for (input = pLDInfo.inputs().dfs_begin(); input!=inEnd; ++input) {
- // already got type - for example, bitcode
- if ((*input)->type() == Input::Script ||
- (*input)->type() == Input::Object ||
- (*input)->type() == Input::DynObj ||
- (*input)->type() == Input::Archive)
- continue;
-
- MemoryArea *input_memory =
- memAreaFactory()->produce((*input)->path(), FileHandle::ReadOnly);
-
- if (input_memory->handler()->isGood()) {
- (*input)->setMemArea(input_memory);
- }
- else {
- error(diag::err_cannot_open_input) << (*input)->name() << (*input)->path();
- return;
- }
-
- LDContext *input_context =
- pLDInfo.contextFactory().produce((*input)->path());
-
- (*input)->setContext(input_context);
- }
-}
-
-void SectLinker::initializeInputTree(const PositionDependentOptions &pPosDepOptions) const
-{
- if (pPosDepOptions.empty())
- fatal(diag::err_no_inputs);
-
- MCLDInfo &info = m_pOption->info();
- PositionDependentOptions::const_iterator option = pPosDepOptions.begin();
- if (1 == pPosDepOptions.size() &&
- ((*option)->type() != PositionDependentOption::INPUT_FILE &&
- (*option)->type() != PositionDependentOption::NAMESPEC) &&
- (*option)->type() != PositionDependentOption::BITCODE) {
- // if we only have one positional options, and the option is
- // not an input file, then emit error message.
- fatal(diag::err_no_inputs);
- }
-
- // ----- Input tree insertion algorithm ----- //
- // The type of the previsou node indicates the direction of the current
- // insertion.
- //
- // root : the parent node who being inserted.
- // mover : the direcion of current movement.
- //
- // for each positional options:
- // insert the options in current root.
- // calculate the next movement
-
- // Initialization
- InputTree::Mover *move = &InputTree::Downward;
- InputTree::iterator root = info.inputs().root();
- PositionDependentOptions::const_iterator optionEnd = pPosDepOptions.end();
- std::stack<InputTree::iterator> returnStack;
-
- while (option != optionEnd ) {
-
- switch ((*option)->type()) {
- /** bitcode **/
- case PositionDependentOption::BITCODE: {
-
- const BitcodeOption *bitcode_option =
- static_cast<const BitcodeOption*>(*option);
-
- // threat bitcode as an external IR in this version.
- info.inputs().insert(root, *move,
- bitcode_option->path()->native(),
- *(bitcode_option->path()),
- Input::External);
-
- info.setBitcode(**root);
-
- // move root on the new created node.
- move->move(root);
-
- // the next file is appended after bitcode file.
- move = &InputTree::Afterward;
- break;
- }
-
- /** input object file **/
- case PositionDependentOption::INPUT_FILE: {
- const InputFileOption *input_file_option =
- static_cast<const InputFileOption*>(*option);
-
- info.inputs().insert(root, *move,
- input_file_option->path()->native(),
- *(input_file_option->path()));
-
- // move root on the new created node.
- move->move(root);
-
- // the next file is appended after object file.
- move = &InputTree::Afterward;
- break;
- }
-
- /** -lnamespec **/
- case PositionDependentOption::NAMESPEC: {
- sys::fs::Path* path = NULL;
- const NamespecOption *namespec_option =
- static_cast<const NamespecOption*>(*option);
-
- // find out the real path of the namespec.
- if (info.attrFactory().constraint().isSharedSystem()) {
- // In the system with shared object support, we can find both archive
- // and shared object.
-
- if (info.attrFactory().last().isStatic()) {
- // with --static, we must search an archive.
- path = info.options().directories().find(namespec_option->namespec(),
- Input::Archive);
- }
- else {
- // otherwise, with --Bdynamic, we can find either an archive or a
- // shared object.
- path = info.options().directories().find(namespec_option->namespec(),
- Input::DynObj);
- }
- }
- else {
- // In the system without shared object support, we only look for an
- // archive.
- path = info.options().directories().find(namespec_option->namespec(),
- Input::Archive);
- }
-
- if (NULL == path)
- fatal(diag::err_cannot_find_namespec) << namespec_option->namespec();
-
- info.inputs().insert(root, *move,
- namespec_option->namespec(),
- *path);
-
- // iterate root on the new created node.
- move->move(root);
-
- // the file after a namespec must be appended afterward.
- move = &InputTree::Afterward;
- break;
- }
-
- /** start group **/
- case PositionDependentOption::START_GROUP:
- info.inputs().enterGroup(root, *move);
- move->move(root);
- returnStack.push(root);
- move = &InputTree::Downward;
- break;
- /** end group **/
- case PositionDependentOption::END_GROUP:
- root = returnStack.top();
- returnStack.pop();
- move = &InputTree::Afterward;
- break;
- case PositionDependentOption::WHOLE_ARCHIVE:
- info.attrFactory().last().setWholeArchive();
- break;
- case PositionDependentOption::NO_WHOLE_ARCHIVE:
- info.attrFactory().last().unsetWholeArchive();
- break;
- case PositionDependentOption::AS_NEEDED:
- info.attrFactory().last().setAsNeeded();
- break;
- case PositionDependentOption::NO_AS_NEEDED:
- info.attrFactory().last().unsetAsNeeded();
- break;
- case PositionDependentOption::ADD_NEEDED:
- info.attrFactory().last().setAddNeeded();
- break;
- case PositionDependentOption::NO_ADD_NEEDED:
- info.attrFactory().last().unsetAddNeeded();
- break;
- case PositionDependentOption::BSTATIC:
- info.attrFactory().last().setStatic();
- break;
- case PositionDependentOption::BDYNAMIC:
- info.attrFactory().last().setDynamic();
- break;
- default:
- fatal(diag::err_cannot_identify_option) << (*option)->position()
- << (uint32_t)(*option)->type();
- } // end of switch
- ++option;
- } // end of while
-
- if (!returnStack.empty()) {
- report_fatal_error("no matched --start-group and --end-group");
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Non-member functions
-static bool CompareOption(const PositionDependentOption* X,
- const PositionDependentOption* Y)
-{
- return (X->position() < Y->position());
-}
-
diff --git a/lib/CodeGen/SectLinkerOption.cpp b/lib/CodeGen/SectLinkerOption.cpp
deleted file mode 100644
index 85d6b10..0000000
--- a/lib/CodeGen/SectLinkerOption.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//===- SectLinkerOption.cpp -------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/CodeGen/SectLinkerOption.h"
-#include "mcld/Support/DerivedPositionDependentOptions.h"
-#include "mcld/Support/RealPath.h"
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// SectLinkerOption
-SectLinkerOption::SectLinkerOption(MCLDInfo &pLDInfo)
- : m_pLDInfo(&pLDInfo) { }
-
-SectLinkerOption::~SectLinkerOption() {
- for (PositionDependentOptions::iterator pdoption = m_PosDepOptions.begin(),
- pdoptionEnd = m_PosDepOptions.end(); pdoption != pdoptionEnd; ++pdoption)
- delete *pdoption;
-}
diff --git a/lib/Core/Android.mk b/lib/Core/Android.mk
new file mode 100644
index 0000000..c30d80c
--- /dev/null
+++ b/lib/Core/Android.mk
@@ -0,0 +1,37 @@
+LOCAL_PATH:= $(call my-dir)
+
+mcld_core_SRC_FILES := \
+ AttributeOption.cpp \
+ BitcodeOption.cpp \
+ Environment.cpp \
+ GeneralOptions.cpp \
+ IRBuilder.cpp \
+ InputTree.cpp \
+ LinkerConfig.cpp \
+ Linker.cpp \
+ Module.cpp \
+ ScriptOptions.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_core_SRC_FILES)
+LOCAL_MODULE:= libmcldCore
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_core_SRC_FILES)
+LOCAL_MODULE:= libmcldCore
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/lib/LD/CIE.cpp b/lib/Core/AttributeOption.cpp
similarity index 64%
copy from lib/LD/CIE.cpp
copy to lib/Core/AttributeOption.cpp
index 5ddb166..d2a7947 100644
--- a/lib/LD/CIE.cpp
+++ b/lib/Core/AttributeOption.cpp
@@ -1,4 +1,4 @@
-//===- CIE.cpp ------------------------------------------------------------===//
+//===- AttributeOption.cpp ------------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,18 +6,17 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/CIE.h>
+#include <mcld/AttributeOption.h>
using namespace mcld;
//===----------------------------------------------------------------------===//
-// CIE
+// AttributeOption
//===----------------------------------------------------------------------===//
-CIE::CIE(MemoryRegion& pRegion, uint8_t pFDEEncode)
- : RegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
+AttributeOption::AttributeOption()
+{
}
-CIE::~CIE()
+AttributeOption::~AttributeOption()
{
}
diff --git a/lib/LD/CIE.cpp b/lib/Core/BitcodeOption.cpp
similarity index 62%
copy from lib/LD/CIE.cpp
copy to lib/Core/BitcodeOption.cpp
index 5ddb166..47d6667 100644
--- a/lib/LD/CIE.cpp
+++ b/lib/Core/BitcodeOption.cpp
@@ -1,4 +1,4 @@
-//===- CIE.cpp ------------------------------------------------------------===//
+//===- BitcodeOption.cpp --------------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,18 +6,22 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/CIE.h>
+#include <mcld/BitcodeOption.h>
using namespace mcld;
//===----------------------------------------------------------------------===//
-// CIE
+// BitcodeOption
//===----------------------------------------------------------------------===//
-CIE::CIE(MemoryRegion& pRegion, uint8_t pFDEEncode)
- : RegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
+BitcodeOption::BitcodeOption()
+ : m_Position(-1) {
}
-CIE::~CIE()
+BitcodeOption::~BitcodeOption()
{
}
+
+bool BitcodeOption::hasDefined() const
+{
+ return (m_Position != -1);
+}
diff --git a/lib/Core/Environment.cpp b/lib/Core/Environment.cpp
new file mode 100644
index 0000000..5755fe7
--- /dev/null
+++ b/lib/Core/Environment.cpp
@@ -0,0 +1,29 @@
+//===- Environment.cpp ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Environment.h>
+#include <mcld/Support/TargetSelect.h>
+
+void mcld::Initialize()
+{
+ static bool is_initialized = false;
+
+ if (is_initialized)
+ return;
+
+ mcld::InitializeAllTargets();
+ mcld::InitializeAllEmulations();
+ mcld::InitializeAllDiagnostics();
+
+ is_initialized = true;
+}
+
+void mcld::Finalize()
+{
+}
+
diff --git a/lib/MC/MCLDOptions.cpp b/lib/Core/GeneralOptions.cpp
similarity index 83%
rename from lib/MC/MCLDOptions.cpp
rename to lib/Core/GeneralOptions.cpp
index 47dbc35..902f753 100644
--- a/lib/MC/MCLDOptions.cpp
+++ b/lib/Core/GeneralOptions.cpp
@@ -1,4 +1,4 @@
-//===- MCLDOptions.cpp ----------------------------------------------------===//
+//===- GeneralOptions.cpp -------------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,23 +6,14 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/MC/MCLDOptions.h>
+#include <mcld/GeneralOptions.h>
#include <mcld/MC/MCLDInput.h>
using namespace mcld;
//===----------------------------------------------------------------------===//
-// ScriptOptions
-ScriptOptions::ScriptOptions()
-{
-}
-
-ScriptOptions::~ScriptOptions()
-{
-}
-
-//===----------------------------------------------------------------------===//
// GeneralOptions
+//===----------------------------------------------------------------------===//
GeneralOptions::GeneralOptions()
: m_pDefaultBitcode(NULL),
m_Verbose(-1),
@@ -51,7 +42,12 @@
m_bPIE(false),
m_bColor(true),
m_bAllowShlibUndefined(true),
- m_bCreateEhFrameHdr(false)
+ m_bCreateEhFrameHdr(false),
+ m_NMagic(false),
+ m_OMagic(false),
+ m_StripDebug(false),
+ m_ExportDynamic(false),
+ m_WarnSharedTextrel(false)
{
}
@@ -73,9 +69,23 @@
{
}
+const mcld::sys::fs::Path& GeneralOptions::sysroot() const
+{
+ return m_SearchDirs.sysroot();
+}
+
void GeneralOptions::setSysroot(const mcld::sys::fs::Path &pSysroot)
{
- m_Sysroot.assign(pSysroot);
+ m_SearchDirs.setSysRoot(pSysroot);
+}
+
+void GeneralOptions::setSOName(const std::string& pName)
+{
+ size_t pos = pName.find_last_of(sys::fs::separator);
+ if (std::string::npos == pos)
+ m_SOName = pName;
+ else
+ m_SOName = pName.substr(pos + 1);
}
void GeneralOptions::addZOption(const ZOption& pOption)
diff --git a/lib/Core/IRBuilder.cpp b/lib/Core/IRBuilder.cpp
new file mode 100644
index 0000000..58c1360
--- /dev/null
+++ b/lib/Core/IRBuilder.cpp
@@ -0,0 +1,413 @@
+//===- IRBuilder.cpp ------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/IRBuilder.h>
+#include <mcld/LD/ELFReader.h>
+#include <mcld/Object/ObjectBuilder.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/Support/MsgHandling.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Helper Functions
+//===----------------------------------------------------------------------===//
+LDFileFormat::Kind GetELFSectionKind(uint32_t pType, const char* pName)
+{
+ // name rules
+ llvm::StringRef name(pName);
+ if (name.startswith(".debug") ||
+ name.startswith(".zdebug") ||
+ name.startswith(".gnu.linkonce.wi.") ||
+ name.startswith(".line") ||
+ name.startswith(".stab"))
+ return LDFileFormat::Debug;
+ if (name.startswith(".comment"))
+ return LDFileFormat::MetaData;
+ if (name.startswith(".interp") || name.startswith(".dynamic"))
+ return LDFileFormat::Note;
+ if (name.startswith(".eh_frame"))
+ return LDFileFormat::EhFrame;
+ if (name.startswith(".eh_frame_hdr"))
+ return LDFileFormat::EhFrameHdr;
+ if (name.startswith(".gcc_except_table"))
+ return LDFileFormat::GCCExceptTable;
+ if (name.startswith(".note.GNU-stack"))
+ return LDFileFormat::StackNote;
+
+ // type rules
+ switch(pType) {
+ case llvm::ELF::SHT_NULL:
+ return LDFileFormat::Null;
+ case llvm::ELF::SHT_INIT_ARRAY:
+ case llvm::ELF::SHT_FINI_ARRAY:
+ case llvm::ELF::SHT_PREINIT_ARRAY:
+ case llvm::ELF::SHT_PROGBITS:
+ return LDFileFormat::Regular;
+ case llvm::ELF::SHT_SYMTAB:
+ case llvm::ELF::SHT_DYNSYM:
+ case llvm::ELF::SHT_STRTAB:
+ case llvm::ELF::SHT_HASH:
+ case llvm::ELF::SHT_DYNAMIC:
+ return LDFileFormat::NamePool;
+ case llvm::ELF::SHT_RELA:
+ case llvm::ELF::SHT_REL:
+ return LDFileFormat::Relocation;
+ case llvm::ELF::SHT_NOBITS:
+ return LDFileFormat::BSS;
+ case llvm::ELF::SHT_NOTE:
+ return LDFileFormat::Note;
+ case llvm::ELF::SHT_GROUP:
+ return LDFileFormat::Group;
+ case llvm::ELF::SHT_GNU_versym:
+ case llvm::ELF::SHT_GNU_verdef:
+ case llvm::ELF::SHT_GNU_verneed:
+ return LDFileFormat::Version;
+ case llvm::ELF::SHT_SHLIB:
+ return LDFileFormat::Target;
+ default:
+ if ((pType >= llvm::ELF::SHT_LOPROC && pType <= llvm::ELF::SHT_HIPROC) ||
+ (pType >= llvm::ELF::SHT_LOOS && pType <= llvm::ELF::SHT_HIOS) ||
+ (pType >= llvm::ELF::SHT_LOUSER && pType <= llvm::ELF::SHT_HIUSER))
+ return LDFileFormat::Target;
+ fatal(diag::err_unsupported_section) << pName << pType;
+ }
+ return LDFileFormat::MetaData;
+}
+
+//===----------------------------------------------------------------------===//
+// IRBuilder
+//===----------------------------------------------------------------------===//
+IRBuilder::IRBuilder(Module& pModule, const LinkerConfig& pConfig)
+ : m_Module(pModule), m_Config(pConfig), m_InputBuilder(pConfig) {
+ m_InputBuilder.setCurrentTree(m_Module.getInputTree());
+}
+
+IRBuilder::~IRBuilder()
+{
+}
+
+/// CreateInput - To create an input file and append it to the input tree.
+Input* IRBuilder::CreateInput(const std::string& pName,
+ const sys::fs::Path& pPath, Input::Type pType)
+{
+ if (Input::Unknown == pType)
+ return ReadInput(pName, pPath);
+
+ m_InputBuilder.createNode<InputTree::Positional>(pName, pPath, pType);
+ Input* input = *m_InputBuilder.getCurrentNode();
+
+ if (!input->hasContext())
+ m_InputBuilder.setContext(*input, false);
+
+ return input;
+}
+
+/// ReadInput - To read an input file and append it to the input tree.
+Input*
+IRBuilder::ReadInput(const std::string& pName, const sys::fs::Path& pPath)
+{
+ m_InputBuilder.createNode<InputTree::Positional>(pName, pPath, Input::Unknown);
+ Input* input = *m_InputBuilder.getCurrentNode();
+
+ if (!input->hasContext())
+ m_InputBuilder.setContext(*input);
+
+ if (!input->hasMemArea())
+ m_InputBuilder.setMemory(*input, FileHandle::ReadOnly, FileHandle::System);
+
+ return input;
+}
+
+/// ReadInput - To read an input file and append it to the input tree.
+Input* IRBuilder::ReadInput(const std::string& pNameSpec)
+{
+ const sys::fs::Path* path = NULL;
+ // find out the real path of the namespec.
+ if (m_InputBuilder.getConstraint().isSharedSystem()) {
+ // In the system with shared object support, we can find both archive
+ // and shared object.
+
+ if (m_InputBuilder.getAttributes().isStatic()) {
+ // with --static, we must search an archive.
+ path = m_Config.options().directories().find(pNameSpec, Input::Archive);
+ }
+ else {
+ // otherwise, with --Bdynamic, we can find either an archive or a
+ // shared object.
+ path = m_Config.options().directories().find(pNameSpec, Input::DynObj);
+ }
+ }
+ else {
+ // In the system without shared object support, we only look for an archive
+ path = m_Config.options().directories().find(pNameSpec, Input::Archive);
+ }
+
+ if (NULL == path) {
+ fatal(diag::err_cannot_find_namespec) << pNameSpec;
+ return NULL;
+ }
+
+ m_InputBuilder.createNode<InputTree::Positional>(pNameSpec, *path);
+ Input* input = *m_InputBuilder.getCurrentNode();
+
+ if (!input->hasContext())
+ m_InputBuilder.setContext(*input);
+
+ if (!input->hasMemArea())
+ m_InputBuilder.setMemory(*input, FileHandle::ReadOnly, FileHandle::System);
+
+ return input;
+}
+
+/// ReadInput - To read an input file and append it to the input tree.
+Input* IRBuilder::ReadInput(raw_mem_ostream& pMemOStream)
+{
+ Input* input = NULL;
+ if (pMemOStream.getMemoryArea().hasHandler()) {
+ m_InputBuilder.createNode<InputTree::Positional>(
+ "memory ostream",
+ pMemOStream.getMemoryArea().handler()->path());
+
+ input = *m_InputBuilder.getCurrentNode();
+ m_InputBuilder.setContext(*input);
+ input->setMemArea(&pMemOStream.getMemoryArea());
+ }
+ else {
+ m_InputBuilder.createNode<InputTree::Positional>("memory ostream", "NAN");
+ input = *m_InputBuilder.getCurrentNode();
+ m_InputBuilder.setContext(*input, false);
+ input->setMemArea(&pMemOStream.getMemoryArea());
+ }
+
+ return input;
+}
+
+/// ReadInput - To read an input file and append it to the input tree.
+Input* IRBuilder::ReadInput(FileHandle& pFileHandle)
+{
+ m_InputBuilder.createNode<InputTree::Positional>("file handler",
+ pFileHandle.path());
+
+ Input* input = *m_InputBuilder.getCurrentNode();
+ if (pFileHandle.path().empty()) {
+ m_InputBuilder.setContext(*input, false);
+ m_InputBuilder.setMemory(*input, pFileHandle.handler(), FileHandle::ReadOnly);
+ }
+ else {
+ m_InputBuilder.setContext(*input, true);
+ m_InputBuilder.setMemory(*input, FileHandle::ReadOnly, FileHandle::System);
+ }
+
+ return input;
+}
+
+/// ReadInput - To read an input file and append it to the input tree.
+Input* IRBuilder::ReadInput(const std::string& pName, void* pRawMemory, size_t pSize)
+{
+ m_InputBuilder.createNode<InputTree::Positional>(pName, "NAN");
+ Input* input = *m_InputBuilder.getCurrentNode();
+ m_InputBuilder.setContext(*input, false);
+ m_InputBuilder.setMemory(*input, pRawMemory, pSize);
+ return input;
+}
+
+bool IRBuilder::StartGroup()
+{
+ if (m_InputBuilder.isInGroup()) {
+ fatal(diag::fatal_forbid_nest_group);
+ return false;
+ }
+ m_InputBuilder.enterGroup();
+ return true;
+}
+
+bool IRBuilder::EndGroup()
+{
+ m_InputBuilder.exitGroup();
+ return true;
+}
+
+void IRBuilder::WholeArchive()
+{
+ m_InputBuilder.getAttributes().setWholeArchive();
+}
+
+void IRBuilder::NoWholeArchive()
+{
+ m_InputBuilder.getAttributes().unsetWholeArchive();
+}
+
+void IRBuilder::AsNeeded()
+{
+ m_InputBuilder.getAttributes().setAsNeeded();
+}
+
+void IRBuilder::NoAsNeeded()
+{
+ m_InputBuilder.getAttributes().unsetAsNeeded();
+}
+
+void IRBuilder::CopyDTNeeded()
+{
+ m_InputBuilder.getAttributes().setAddNeeded();
+}
+
+void IRBuilder::NoCopyDTNeeded()
+{
+ m_InputBuilder.getAttributes().unsetAddNeeded();
+}
+
+void IRBuilder::AgainstShared()
+{
+ m_InputBuilder.getAttributes().setDynamic();
+}
+
+void IRBuilder::AgainstStatic()
+{
+ m_InputBuilder.getAttributes().setStatic();
+}
+
+LDSection* IRBuilder::CreateELFHeader(Input& pInput,
+ const std::string& pName,
+ uint32_t pType,
+ uint32_t pFlag,
+ uint32_t pAlign)
+{
+ // Create section header
+ LDFileFormat::Kind kind = GetELFSectionKind(pType, pName.c_str());
+ LDSection* header = LDSection::Create(pName, kind, pType, pFlag);
+ header->setAlign(pAlign);
+
+ // Append section header in input
+ pInput.context()->appendSection(*header);
+ return header;
+}
+
+/// CreateSectionData - To create a section data for given pSection.
+SectionData* IRBuilder::CreateSectionData(LDSection& pSection)
+{
+ assert(!pSection.hasSectionData() && "pSection already has section data.");
+
+ SectionData* sect_data = SectionData::Create(pSection);
+ pSection.setSectionData(sect_data);
+ return sect_data;
+}
+
+/// CreateRelocData - To create a relocation data for given pSection.
+RelocData* IRBuilder::CreateRelocData(LDSection &pSection)
+{
+ assert(!pSection.hasRelocData() && "pSection already has relocation data.");
+
+ RelocData* reloc_data = RelocData::Create(pSection);
+ pSection.setRelocData(reloc_data);
+ return reloc_data;
+}
+
+/// CreateEhFrame - To create a eh_frame for given pSection
+EhFrame* IRBuilder::CreateEhFrame(LDSection& pSection)
+{
+ assert(!pSection.hasEhFrame() && "pSection already has eh_frame.");
+
+ EhFrame* eh_frame = new EhFrame(pSection);
+ pSection.setEhFrame(eh_frame);
+ return eh_frame;
+}
+
+/// CreateBSS - To create a bss section for given pSection
+SectionData* IRBuilder::CreateBSS(LDSection& pSection)
+{
+ assert(!pSection.hasSectionData() && "pSection already has section data.");
+ assert((pSection.kind() == LDFileFormat::BSS) && "pSection is not a BSS section.");
+
+ SectionData* sect_data = SectionData::Create(pSection);
+ pSection.setSectionData(sect_data);
+
+ /* value, valsize, size*/
+ FillFragment* frag = new FillFragment(0x0, 1, pSection.size());
+
+ ObjectBuilder::AppendFragment(*frag, *sect_data);
+ return sect_data;
+}
+
+/// CreateRegion - To create a region fragment in the input file.
+Fragment* IRBuilder::CreateRegion(Input& pInput, size_t pOffset, size_t pLength)
+{
+ if (!pInput.hasMemArea()) {
+ fatal(diag::fatal_cannot_read_input) << pInput.path();
+ return NULL;
+ }
+
+ if (0 == pLength)
+ return new FillFragment(0x0, 0, 0);
+
+ MemoryRegion* region = pInput.memArea()->request(pOffset, pLength);
+
+ if (NULL == region)
+ return new FillFragment(0x0, 0, 0);
+
+ return new RegionFragment(*region);
+}
+
+/// CreateRegion - To create a region fragment wrapping the given memory
+Fragment* IRBuilder::CreateRegion(void* pMemory, size_t pLength)
+{
+ if (0 == pLength)
+ return new FillFragment(0x0, 0, 0);
+
+ MemoryRegion* region = MemoryRegion::Create(pMemory, pLength);
+ if (NULL == region)
+ return new FillFragment(0x0, 0, 0);
+
+ return new RegionFragment(*region);
+}
+
+/// AppendFragment - To append pFrag to the given SectionData pSD
+uint64_t IRBuilder::AppendFragment(Fragment& pFrag, SectionData& pSD)
+{
+ uint64_t size = ObjectBuilder::AppendFragment(pFrag,
+ pSD,
+ pSD.getSection().align());
+ pSD.getSection().setSize(pSD.getSection().size() + size);
+ return size;
+}
+
+/// AppendRelocation - To append an relocation to the given RelocData pRD.
+void IRBuilder::AppendRelocation(Relocation& pRelocation, RelocData& pRD)
+{
+ pRD.getFragmentList().push_back(&pRelocation);
+}
+
+/// AppendEhFrame - To append a fragment to EhFrame.
+uint64_t IRBuilder::AppendEhFrame(Fragment& pFrag, EhFrame& pEhFrame)
+{
+ uint64_t size = ObjectBuilder::AppendFragment(pFrag,
+ pEhFrame.getSectionData(),
+ pEhFrame.getSection().align());
+ pEhFrame.getSection().setSize(pEhFrame.getSection().size() + size);
+ return size;
+}
+
+/// AppendEhFrame - To append a FDE to the given EhFrame pEhFram.
+uint64_t IRBuilder::AppendEhFrame(EhFrame::FDE& pFDE, EhFrame& pEhFrame)
+{
+ pEhFrame.addFDE(pFDE);
+ pEhFrame.getSection().setSize(pEhFrame.getSection().size() + pFDE.size());
+ return pFDE.size();
+}
+
+/// AppendEhFrame - To append a CIE to the given EhFrame pEhFram.
+uint64_t IRBuilder::AppendEhFrame(EhFrame::CIE& pCIE, EhFrame& pEhFrame)
+{
+ pEhFrame.addCIE(pCIE);
+ pEhFrame.getSection().setSize(pEhFrame.getSection().size() + pCIE.size());
+ return pCIE.size();
+}
+
diff --git a/lib/MC/InputTree.cpp b/lib/Core/InputTree.cpp
similarity index 66%
rename from lib/MC/InputTree.cpp
rename to lib/Core/InputTree.cpp
index 1416b6a..15f6f5e 100644
--- a/lib/MC/InputTree.cpp
+++ b/lib/Core/InputTree.cpp
@@ -6,8 +6,7 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/MC/InputTree.h>
-#include <mcld/MC/InputFactory.h>
+#include <mcld/InputTree.h>
using namespace mcld;
@@ -16,15 +15,8 @@
//===----------------------------------------------------------------------===//
// InputTree
-InputTree::InputTree(InputFactory& pInputFactory)
- : m_FileFactory(pInputFactory) {
-}
-
-InputTree::~InputTree()
-{
-}
-
-InputTree& InputTree::merge(TreeIteratorBase pRoot,
+//===----------------------------------------------------------------------===//
+InputTree& InputTree::merge(TreeIteratorBase pRoot,
const InputTree::Mover& pMover,
InputTree& pTree)
{
@@ -41,18 +33,6 @@
return *this;
}
-InputTree& InputTree::insert(TreeIteratorBase pRoot,
- const InputTree::Mover& pMover,
- const std::string& pNamespec,
- const sys::fs::Path& pPath,
- unsigned int pType)
-{
- BinaryTree<Input>::node_type* node = createNode();
- node->data = m_FileFactory.produce(pNamespec, pPath, pType);
- pMover.connect(pRoot, iterator(node));
- return *this;
-}
-
InputTree& InputTree::enterGroup(TreeIteratorBase pRoot,
const InputTree::Mover& pMover)
{
@@ -63,45 +43,44 @@
InputTree& InputTree::insert(TreeIteratorBase pRoot,
const InputTree::Mover& pMover,
- const mcld::Input& pInput)
+ mcld::Input& pInput)
{
BinaryTree<Input>::node_type* node = createNode();
- node->data = const_cast<mcld::Input*>(&pInput);
+ node->data = &pInput;
pMover.connect(pRoot, iterator(node));
return *this;
}
-
-
//===----------------------------------------------------------------------===//
// non-member functions
+//===----------------------------------------------------------------------===//
bool mcld::isGroup(const InputTree::iterator& pos)
{
- return !pos.hasData();
+ return !pos.hasData() && !pos.isRoot();
}
bool mcld::isGroup(const InputTree::const_iterator& pos)
{
- return !pos.hasData();
+ return !pos.hasData() && !pos.isRoot();
}
bool mcld::isGroup(const InputTree::dfs_iterator& pos)
{
- return !pos.hasData();
+ return !pos.hasData() && !pos.isRoot();
}
bool mcld::isGroup(const InputTree::const_dfs_iterator& pos)
{
- return !pos.hasData();
+ return !pos.hasData() && !pos.isRoot();
}
bool mcld::isGroup(const InputTree::bfs_iterator& pos)
{
- return !pos.hasData();
+ return !pos.hasData() && !pos.isRoot();
}
bool mcld::isGroup(const InputTree::const_bfs_iterator& pos)
{
- return !pos.hasData();
+ return !pos.hasData() && !pos.isRoot();
}
diff --git a/lib/Core/Linker.cpp b/lib/Core/Linker.cpp
new file mode 100644
index 0000000..7262537
--- /dev/null
+++ b/lib/Core/Linker.cpp
@@ -0,0 +1,257 @@
+//===- Linker.cpp ---------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Linker.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/Module.h>
+#include <mcld/IRBuilder.h>
+
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/raw_ostream.h>
+
+#include <mcld/Object/ObjectLinker.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/Target/TargetLDBackend.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/FragmentRef.h>
+
+#include <cassert>
+
+using namespace mcld;
+
+Linker::Linker()
+ : m_pConfig(NULL), m_pModule(NULL), m_pIRBuilder(NULL),
+ m_pTarget(NULL), m_pBackend(NULL), m_pObjLinker(NULL) {
+}
+
+Linker::~Linker()
+{
+ reset();
+}
+
+bool Linker::config(LinkerConfig& pConfig)
+{
+ m_pConfig = &pConfig;
+
+ if (!initTarget())
+ return false;
+
+ if (!initBackend())
+ return false;
+
+ if (!initEmulator())
+ return false;
+
+ if (!initOStream())
+ return false;
+
+ return true;
+}
+
+bool Linker::link(Module& pModule, IRBuilder& pBuilder)
+{
+ assert(NULL != m_pConfig);
+
+ m_pIRBuilder = &pBuilder;
+ m_pObjLinker = new ObjectLinker(*m_pConfig,
+ pModule,
+ m_pIRBuilder->getInputBuilder(),
+ *m_pBackend);
+
+ // 2. - initialize FragmentLinker
+ if (!m_pObjLinker->initFragmentLinker())
+ return false;
+
+ // 3. - initialize output's standard sections
+ if (!m_pObjLinker->initStdSections())
+ return false;
+
+ // 4. - normalize the input tree
+ m_pObjLinker->normalize();
+
+ if (m_pConfig->options().trace()) {
+ static int counter = 0;
+ mcld::outs() << "** name\ttype\tpath\tsize (" << pModule.getInputTree().size() << ")\n";
+ InputTree::const_dfs_iterator input, inEnd = pModule.getInputTree().dfs_end();
+ for (input=pModule.getInputTree().dfs_begin(); input!=inEnd; ++input) {
+ mcld::outs() << counter++ << " * " << (*input)->name();
+ switch((*input)->type()) {
+ case Input::Archive:
+ mcld::outs() << "\tarchive\t(";
+ break;
+ case Input::Object:
+ mcld::outs() << "\tobject\t(";
+ break;
+ case Input::DynObj:
+ mcld::outs() << "\tshared\t(";
+ break;
+ case Input::Script:
+ mcld::outs() << "\tscript\t(";
+ break;
+ case Input::External:
+ mcld::outs() << "\textern\t(";
+ break;
+ default:
+ unreachable(diag::err_cannot_trace_file) << (*input)->type()
+ << (*input)->name()
+ << (*input)->path();
+ }
+ mcld::outs() << (*input)->path() << ")\n";
+ }
+ }
+
+ // 5. - check if we can do static linking and if we use split-stack.
+ if (!m_pObjLinker->linkable())
+ return Diagnose();
+
+ // 6. - read all relocation entries from input files
+ m_pObjLinker->readRelocations();
+
+ // 7. - merge all sections
+ if (!m_pObjLinker->mergeSections())
+ return false;
+
+ // 8. - add standard symbols and target-dependent symbols
+ // m_pObjLinker->addUndefSymbols();
+ if (!m_pObjLinker->addStandardSymbols() ||
+ !m_pObjLinker->addTargetSymbols())
+ return false;
+
+ // 9. - scan all relocation entries by output symbols.
+ m_pObjLinker->scanRelocations();
+
+ // 10.a - pre-layout
+ m_pObjLinker->prelayout();
+
+ // 10.b - linear layout
+ m_pObjLinker->layout();
+
+ // 10.c - post-layout (create segment, instruction relaxing)
+ m_pObjLinker->postlayout();
+
+ // 11. - finalize symbol value
+ m_pObjLinker->finalizeSymbolValue();
+
+ // 12. - apply relocations
+ m_pObjLinker->relocation();
+
+ if (!Diagnose())
+ return false;
+ return true;
+}
+
+bool Linker::emit(MemoryArea& pOutput)
+{
+ // 13. - write out output
+ m_pObjLinker->emitOutput(pOutput);
+
+ // 14. - post processing
+ m_pObjLinker->postProcessing(pOutput);
+
+ if (!Diagnose())
+ return false;
+
+ return true;
+}
+
+bool Linker::emit(const std::string& pPath)
+{
+ FileHandle file;
+ FileHandle::Permission perm = 0755;
+ if (!file.open(pPath,
+ FileHandle::ReadWrite | FileHandle::Truncate | FileHandle::Create,
+ perm)) {
+ error(diag::err_cannot_open_output_file) << "Linker::emit()" << pPath;
+ return false;
+ }
+
+ MemoryArea* output = new MemoryArea(file);
+
+ bool result = emit(*output);
+
+ delete output;
+ file.close();
+ return result;
+}
+
+bool Linker::emit(int pFileDescriptor)
+{
+ FileHandle file;
+ file.delegate(pFileDescriptor);
+ MemoryArea* output = new MemoryArea(file);
+
+ bool result = emit(*output);
+
+ delete output;
+ file.close();
+ return result;
+}
+
+bool Linker::reset()
+{
+ m_pConfig = NULL;
+ m_pModule = NULL;
+ m_pIRBuilder = NULL;
+ m_pTarget = NULL;
+
+ delete m_pBackend;
+ m_pBackend = NULL;
+
+ delete m_pObjLinker;
+ m_pObjLinker = NULL;
+
+ LDSection::Clear();
+ LDSymbol::Clear();
+ FragmentRef::Clear();
+ return true;
+}
+
+bool Linker::initTarget()
+{
+ assert(NULL != m_pConfig);
+
+ std::string error;
+ m_pTarget = TargetRegistry::lookupTarget(m_pConfig->triple().str(), error);
+ if (NULL == m_pTarget) {
+ fatal(diag::fatal_cannot_init_target) << m_pConfig->triple().str() << error;
+ return false;
+ }
+ return true;
+}
+
+bool Linker::initBackend()
+{
+ assert(NULL != m_pTarget);
+ m_pBackend = m_pTarget->createLDBackend(*m_pConfig);
+ if (NULL == m_pBackend) {
+ fatal(diag::fatal_cannot_init_backend) << m_pConfig->triple().str();
+ return false;
+ }
+ return true;
+}
+
+bool Linker::initEmulator()
+{
+ assert(NULL != m_pTarget && NULL != m_pConfig);
+ return m_pTarget->emulate(m_pConfig->triple().str(), *m_pConfig);
+}
+
+bool Linker::initOStream()
+{
+ assert(NULL != m_pConfig);
+
+ mcld::outs().setColor(m_pConfig->options().color());
+ mcld::errs().setColor(m_pConfig->options().color());
+
+ return true;
+}
+
diff --git a/lib/Core/LinkerConfig.cpp b/lib/Core/LinkerConfig.cpp
new file mode 100644
index 0000000..d94bbe2
--- /dev/null
+++ b/lib/Core/LinkerConfig.cpp
@@ -0,0 +1,62 @@
+//===- LinkerConfig.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LinkerConfig.h>
+#include <mcld/Config/Config.h>
+
+#include <mcld/Support/MsgHandling.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// LinkerConfig
+//===----------------------------------------------------------------------===//
+LinkerConfig::LinkerConfig()
+ : m_Options(),
+ m_Scripts(),
+ m_Bitcode(),
+ m_Attribute(),
+ m_Triple(),
+ m_CodeGenType(Unknown)
+{
+ // FIXME: is here the right place to hold this?
+ InitializeDiagnosticEngine(*this);
+}
+
+LinkerConfig::LinkerConfig(const std::string& pTripleString)
+ : m_Options(),
+ m_Scripts(),
+ m_Bitcode(),
+ m_Attribute(),
+ m_Triple(pTripleString),
+ m_CodeGenType(Unknown)
+{
+ // FIXME: is here the right place to hold this?
+ InitializeDiagnosticEngine(*this);
+}
+
+LinkerConfig::~LinkerConfig()
+{
+ // FIXME: is here the right place to hold this?
+ FinalizeDiagnosticEngine();
+}
+
+void LinkerConfig::setTriple(const llvm::Triple& pTriple)
+{
+ m_Triple = pTriple;
+}
+
+void LinkerConfig::setTriple(const std::string& pTriple)
+{
+ m_Triple.setTriple(pTriple);
+}
+
+const char* LinkerConfig::version()
+{
+ return MCLD_VERSION;
+}
diff --git a/lib/Core/Module.cpp b/lib/Core/Module.cpp
new file mode 100644
index 0000000..e186aaf
--- /dev/null
+++ b/lib/Core/Module.cpp
@@ -0,0 +1,56 @@
+//===- Module.cpp ---------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Module.h>
+#include <mcld/Fragment/FragmentRef.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/NamePool.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/StaticResolver.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Module
+//===----------------------------------------------------------------------===//
+Module::Module()
+ : m_NamePool(1024) {
+}
+
+Module::Module(const std::string& pName)
+ : m_Name(pName), m_NamePool(1024) {
+}
+
+Module::~Module()
+{
+}
+
+// Following two functions will be obsolette when we have new section merger.
+LDSection* Module::getSection(const std::string& pName)
+{
+ iterator sect, sectEnd = end();
+ for (sect = begin(); sect != sectEnd; ++sect) {
+ if ((*sect)->name() == pName)
+ return *sect;
+ }
+ return NULL;
+}
+
+const LDSection* Module::getSection(const std::string& pName) const
+{
+ const_iterator sect, sectEnd = end();
+ for (sect = begin(); sect != sectEnd; ++sect) {
+ if ((*sect)->name() == pName)
+ return *sect;
+ }
+ return NULL;
+}
+
diff --git a/lib/LD/CIE.cpp b/lib/Core/ScriptOptions.cpp
similarity index 64%
copy from lib/LD/CIE.cpp
copy to lib/Core/ScriptOptions.cpp
index 5ddb166..930eeea 100644
--- a/lib/LD/CIE.cpp
+++ b/lib/Core/ScriptOptions.cpp
@@ -1,4 +1,4 @@
-//===- CIE.cpp ------------------------------------------------------------===//
+//===- ScriptOptions.cpp --------------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,18 +6,18 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/CIE.h>
+#include <mcld/ScriptOptions.h>
using namespace mcld;
//===----------------------------------------------------------------------===//
-// CIE
+// ScriptOptions
//===----------------------------------------------------------------------===//
-CIE::CIE(MemoryRegion& pRegion, uint8_t pFDEEncode)
- : RegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
-}
-
-CIE::~CIE()
+ScriptOptions::ScriptOptions()
{
}
+
+ScriptOptions::~ScriptOptions()
+{
+}
+
diff --git a/lib/LD/AlignFragment.cpp b/lib/Fragment/AlignFragment.cpp
similarity index 74%
rename from lib/LD/AlignFragment.cpp
rename to lib/Fragment/AlignFragment.cpp
index 5154b0b..7cc1065 100644
--- a/lib/LD/AlignFragment.cpp
+++ b/lib/Fragment/AlignFragment.cpp
@@ -6,8 +6,9 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/LD/AlignFragment.h>
+#include <mcld/Fragment/AlignFragment.h>
+#include <llvm/Support/MathExtras.h>
#include <mcld/LD/SectionData.h>
using namespace mcld;
@@ -25,3 +26,13 @@
m_bEmitNops(false) {
}
+size_t AlignFragment::size() const
+{
+ assert(hasOffset() && "AlignFragment::size() should not be called before layout.");
+ uint64_t size = llvm::OffsetToAlignment(getOffset(), m_Alignment);
+ if (size > m_MaxBytesToEmit)
+ return 0;
+
+ return size;
+}
+
diff --git a/lib/Fragment/Android.mk b/lib/Fragment/Android.mk
new file mode 100644
index 0000000..0da2051
--- /dev/null
+++ b/lib/Fragment/Android.mk
@@ -0,0 +1,36 @@
+LOCAL_PATH:= $(call my-dir)
+
+mcld_fragment_SRC_FILES := \
+ AlignFragment.cpp \
+ FillFragment.cpp \
+ Fragment.cpp \
+ FragmentLinker.cpp \
+ FragmentRef.cpp \
+ NullFragment.cpp \
+ RegionFragment.cpp \
+ Relocation.cpp \
+ Stub.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_fragment_SRC_FILES)
+LOCAL_MODULE:= libmcldFragment
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_fragment_SRC_FILES)
+LOCAL_MODULE:= libmcldFragment
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/lib/LD/FillFragment.cpp b/lib/Fragment/FillFragment.cpp
similarity index 95%
rename from lib/LD/FillFragment.cpp
rename to lib/Fragment/FillFragment.cpp
index 8f127ca..16de4f0 100644
--- a/lib/LD/FillFragment.cpp
+++ b/lib/Fragment/FillFragment.cpp
@@ -6,8 +6,7 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
-#include <mcld/LD/FillFragment.h>
+#include <mcld/Fragment/FillFragment.h>
#include <mcld/LD/SectionData.h>
#include <cassert>
diff --git a/lib/LD/Fragment.cpp b/lib/Fragment/Fragment.cpp
similarity index 67%
rename from lib/LD/Fragment.cpp
rename to lib/Fragment/Fragment.cpp
index 6e1e3a7..df66694 100644
--- a/lib/LD/Fragment.cpp
+++ b/lib/Fragment/Fragment.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include <mcld/LD/Fragment.h>
+#include <mcld/Fragment/Fragment.h>
#include <llvm/Support/DataTypes.h>
@@ -19,11 +19,11 @@
// Fragment
//===----------------------------------------------------------------------===//
Fragment::Fragment()
- : m_Kind(Type(~0)), m_pParent(NULL), m_Offset(~uint64_t(0)), m_LayoutOrder(~(0U)) {
+ : m_Kind(Type(~0)), m_pParent(NULL), m_Offset(~uint64_t(0)) {
}
Fragment::Fragment(Type pKind, SectionData *pParent)
- : m_Kind(pKind), m_pParent(pParent), m_Offset(~uint64_t(0)), m_LayoutOrder(~(0U)) {
+ : m_Kind(pKind), m_pParent(pParent), m_Offset(~uint64_t(0)) {
if (NULL != m_pParent)
m_pParent->getFragmentList().push_back(this);
}
@@ -32,3 +32,14 @@
{
}
+uint64_t Fragment::getOffset() const
+{
+ assert(hasOffset() && "Cannot getOffset() before setting it up.");
+ return m_Offset;
+}
+
+bool Fragment::hasOffset() const
+{
+ return (m_Offset != ~uint64_t(0));
+}
+
diff --git a/lib/Fragment/FragmentLinker.cpp b/lib/Fragment/FragmentLinker.cpp
new file mode 100644
index 0000000..4ad3d90
--- /dev/null
+++ b/lib/Fragment/FragmentLinker.cpp
@@ -0,0 +1,681 @@
+//===- FragmentLinker.cpp -------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the FragmentLinker class
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Fragment/FragmentLinker.h>
+
+#include <llvm/Support/Host.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/Casting.h>
+
+#include <mcld/LinkerConfig.h>
+#include <mcld/Module.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/LD/BranchIslandFactory.h>
+#include <mcld/LD/Layout.h>
+#include <mcld/LD/Resolver.h>
+#include <mcld/LD/LDContext.h>
+#include <mcld/LD/RelocationFactory.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/LD/SectionRules.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Target/TargetLDBackend.h>
+
+using namespace mcld;
+
+/// Constructor
+FragmentLinker::FragmentLinker(const LinkerConfig& pConfig,
+ Module& pModule,
+ TargetLDBackend& pBackend)
+
+ : m_Config(pConfig),
+ m_Module(pModule),
+ m_Backend(pBackend) {
+}
+
+/// Destructor
+FragmentLinker::~FragmentLinker()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// Symbol Operations
+//===----------------------------------------------------------------------===//
+/// addSymbolFromObject - add a symbol from object file and resolve it
+/// immediately
+LDSymbol* FragmentLinker::addSymbolFromObject(const llvm::StringRef& pName,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBinding,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
+ FragmentRef* pFragmentRef,
+ ResolveInfo::Visibility pVisibility)
+{
+
+ // Step 1. calculate a Resolver::Result
+ // resolved_result is a triple <resolved_info, existent, override>
+ Resolver::Result resolved_result;
+ ResolveInfo old_info; // used for arrange output symbols
+
+ if (pBinding == ResolveInfo::Local) {
+ // if the symbol is a local symbol, create a LDSymbol for input, but do not
+ // resolve them.
+ resolved_result.info = m_Module.getNamePool().createSymbol(pName,
+ false,
+ pType,
+ pDesc,
+ pBinding,
+ pSize,
+ pVisibility);
+
+ // No matter if there is a symbol with the same name, insert the symbol
+ // into output symbol table. So, we let the existent false.
+ resolved_result.existent = false;
+ resolved_result.overriden = true;
+ }
+ else {
+ // if the symbol is not local, insert and resolve it immediately
+ m_Module.getNamePool().insertSymbol(pName, false, pType, pDesc, pBinding,
+ pSize, pVisibility,
+ &old_info, resolved_result);
+ }
+
+ // the return ResolveInfo should not NULL
+ assert(NULL != resolved_result.info);
+
+ /// Step 2. create an input LDSymbol.
+ // create a LDSymbol for the input file.
+ LDSymbol* input_sym = LDSymbol::Create(*resolved_result.info);
+ input_sym->setFragmentRef(pFragmentRef);
+ input_sym->setValue(pValue);
+
+ // Step 3. Set up corresponding output LDSymbol
+ LDSymbol* output_sym = resolved_result.info->outSymbol();
+ bool has_output_sym = (NULL != output_sym);
+ if (!resolved_result.existent || !has_output_sym) {
+ // it is a new symbol, the output_sym should be NULL.
+ assert(NULL == output_sym);
+
+ if (pType == ResolveInfo::Section) {
+ // if it is a section symbol, its output LDSymbol is the input LDSymbol.
+ output_sym = input_sym;
+ }
+ else {
+ // if it is a new symbol, create a LDSymbol for the output
+ output_sym = LDSymbol::Create(*resolved_result.info);
+ }
+ resolved_result.info->setSymPtr(output_sym);
+ }
+
+ if (resolved_result.overriden || !has_output_sym) {
+ // symbol can be overriden only if it exists.
+ assert(output_sym != NULL);
+
+ // should override output LDSymbol
+ output_sym->setFragmentRef(pFragmentRef);
+ output_sym->setValue(pValue);
+ }
+
+ // Step 4. Adjust the position of output LDSymbol.
+ // After symbol resolution, visibility is changed to the most restrict one.
+ // we need to arrange its position in the output symbol. We arrange the
+ // positions by sorting symbols in SymbolCategory.
+ if (pType != ResolveInfo::Section) {
+ if (!has_output_sym) {
+ // We merge sections when reading them. So we do not need to output symbols
+ // with section type
+
+ // No matter the symbol is already in the output or not, add it if it
+ // should be forcefully set local.
+ if (shouldForceLocal(*resolved_result.info))
+ m_Module.getSymbolTable().forceLocal(*output_sym);
+ else {
+ // the symbol should not be forcefully local.
+ m_Module.getSymbolTable().add(*output_sym);
+ }
+ }
+ else if (resolved_result.overriden) {
+ if (!shouldForceLocal(old_info) ||
+ !shouldForceLocal(*resolved_result.info)) {
+ // If the old info and the new info are both forcefully local, then
+ // we should keep the output_sym in forcefully local category. Else,
+ // we should re-sort the output_sym
+ m_Module.getSymbolTable().arrange(*output_sym, old_info);
+ }
+ }
+ }
+
+ return input_sym;
+}
+
+/// addSymbolFromDynObj - add a symbol from object file and resolve it
+/// immediately
+LDSymbol* FragmentLinker::addSymbolFromDynObj(const llvm::StringRef& pName,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBinding,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
+ FragmentRef* pFragmentRef,
+ ResolveInfo::Visibility pVisibility)
+{
+ // We don't need sections of dynamic objects. So we ignore section symbols.
+ if (pType == ResolveInfo::Section)
+ return NULL;
+
+ // ignore symbols with local binding or that have internal or hidden
+ // visibility
+ if (pBinding == ResolveInfo::Local ||
+ pVisibility == ResolveInfo::Internal ||
+ pVisibility == ResolveInfo::Hidden)
+ return NULL;
+
+ // A protected symbol in a shared library must be treated as a
+ // normal symbol when viewed from outside the shared library.
+ if (pVisibility == ResolveInfo::Protected)
+ pVisibility = ResolveInfo::Default;
+
+ // insert symbol and resolve it immediately
+ // resolved_result is a triple <resolved_info, existent, override>
+ Resolver::Result resolved_result;
+ m_Module.getNamePool().insertSymbol(pName, true, pType, pDesc,
+ pBinding, pSize, pVisibility,
+ NULL, resolved_result);
+
+ // the return ResolveInfo should not NULL
+ assert(NULL != resolved_result.info);
+
+ // create a LDSymbol for the input file.
+ LDSymbol* input_sym = LDSymbol::Create(*resolved_result.info);
+ input_sym->setFragmentRef(pFragmentRef);
+ input_sym->setValue(pValue);
+
+ LDSymbol* output_sym = NULL;
+ if (!resolved_result.existent) {
+ // we get a new symbol, leave it as NULL
+ resolved_result.info->setSymPtr(NULL);
+ }
+ else {
+ // we saw the symbol before, but the output_sym still may be NULL.
+ output_sym = resolved_result.info->outSymbol();
+ }
+
+ if (output_sym != NULL) {
+ // After symbol resolution, visibility is changed to the most restrict one.
+ // If we are not doing incremental linking, then any symbol with hidden
+ // or internal visibility is forcefully set as a local symbol.
+ if (shouldForceLocal(*resolved_result.info)) {
+ m_Module.getSymbolTable().forceLocal(*output_sym);
+ }
+ }
+
+ return input_sym;
+}
+
+/// defineSymbolForcefully - define an output symbol and override it immediately
+LDSymbol* FragmentLinker::defineSymbolForcefully(const llvm::StringRef& pName,
+ bool pIsDyn,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBinding,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
+ FragmentRef* pFragmentRef,
+ ResolveInfo::Visibility pVisibility)
+{
+ ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
+ LDSymbol* output_sym = NULL;
+ if (NULL == info) {
+ // the symbol is not in the pool, create a new one.
+ // create a ResolveInfo
+ Resolver::Result result;
+ m_Module.getNamePool().insertSymbol(pName, pIsDyn, pType, pDesc,
+ pBinding, pSize, pVisibility,
+ NULL, result);
+ assert(!result.existent);
+
+ // create a output LDSymbol
+ output_sym = LDSymbol::Create(*result.info);
+ result.info->setSymPtr(output_sym);
+
+ if (shouldForceLocal(*result.info))
+ m_Module.getSymbolTable().forceLocal(*output_sym);
+ else
+ m_Module.getSymbolTable().add(*output_sym);
+ }
+ else {
+ // the symbol is already in the pool, override it
+ ResolveInfo old_info;
+ old_info.override(*info);
+
+ info->setSource(pIsDyn);
+ info->setType(pType);
+ info->setDesc(pDesc);
+ info->setBinding(pBinding);
+ info->setVisibility(pVisibility);
+ info->setIsSymbol(true);
+ info->setSize(pSize);
+
+ output_sym = info->outSymbol();
+ if (NULL != output_sym)
+ m_Module.getSymbolTable().arrange(*output_sym, old_info);
+ else {
+ // create a output LDSymbol
+ output_sym = LDSymbol::Create(*info);
+ info->setSymPtr(output_sym);
+
+ m_Module.getSymbolTable().add(*output_sym);
+ }
+ }
+
+ if (NULL != output_sym) {
+ output_sym->setFragmentRef(pFragmentRef);
+ output_sym->setValue(pValue);
+ }
+
+ return output_sym;
+}
+
+/// defineSymbolAsRefered - define an output symbol and override it immediately
+LDSymbol* FragmentLinker::defineSymbolAsRefered(const llvm::StringRef& pName,
+ bool pIsDyn,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBinding,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
+ FragmentRef* pFragmentRef,
+ ResolveInfo::Visibility pVisibility)
+{
+ ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
+
+ if (NULL == info || !(info->isUndef() || info->isDyn())) {
+ // only undefined symbol and dynamic symbol can make a reference.
+ return NULL;
+ }
+
+ // the symbol is already in the pool, override it
+ ResolveInfo old_info;
+ old_info.override(*info);
+
+ info->setSource(pIsDyn);
+ info->setType(pType);
+ info->setDesc(pDesc);
+ info->setBinding(pBinding);
+ info->setVisibility(pVisibility);
+ info->setIsSymbol(true);
+ info->setSize(pSize);
+
+ LDSymbol* output_sym = info->outSymbol();
+ if (NULL != output_sym) {
+ output_sym->setFragmentRef(pFragmentRef);
+ output_sym->setValue(pValue);
+ m_Module.getSymbolTable().arrange(*output_sym, old_info);
+ }
+ else {
+ // create a output LDSymbol
+ output_sym = LDSymbol::Create(*info);
+ info->setSymPtr(output_sym);
+
+ m_Module.getSymbolTable().add(*output_sym);
+ }
+
+ return output_sym;
+}
+
+/// defineAndResolveSymbolForcefully - define an output symbol and resolve it
+/// immediately
+LDSymbol* FragmentLinker::defineAndResolveSymbolForcefully(const llvm::StringRef& pName,
+ bool pIsDyn,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBinding,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
+ FragmentRef* pFragmentRef,
+ ResolveInfo::Visibility pVisibility)
+{
+ // Result is <info, existent, override>
+ Resolver::Result result;
+ ResolveInfo old_info;
+ m_Module.getNamePool().insertSymbol(pName, pIsDyn, pType, pDesc, pBinding,
+ pSize, pVisibility,
+ &old_info, result);
+
+ LDSymbol* output_sym = result.info->outSymbol();
+ bool has_output_sym = (NULL != output_sym);
+
+ if (!result.existent || !has_output_sym) {
+ output_sym = LDSymbol::Create(*result.info);
+ result.info->setSymPtr(output_sym);
+ }
+
+ if (result.overriden || !has_output_sym) {
+ output_sym->setFragmentRef(pFragmentRef);
+ output_sym->setValue(pValue);
+ }
+
+ // After symbol resolution, the visibility is changed to the most restrict.
+ // arrange the output position
+ if (shouldForceLocal(*result.info))
+ m_Module.getSymbolTable().forceLocal(*output_sym);
+ else if (has_output_sym)
+ m_Module.getSymbolTable().arrange(*output_sym, old_info);
+ else
+ m_Module.getSymbolTable().add(*output_sym);
+
+ return output_sym;
+}
+
+/// defineAndResolveSymbolAsRefered - define an output symbol and resolve it
+/// immediately.
+LDSymbol* FragmentLinker::defineAndResolveSymbolAsRefered(const llvm::StringRef& pName,
+ bool pIsDyn,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBinding,
+ ResolveInfo::SizeType pSize,
+ LDSymbol::ValueType pValue,
+ FragmentRef* pFragmentRef,
+ ResolveInfo::Visibility pVisibility)
+{
+ ResolveInfo* info = m_Module.getNamePool().findInfo(pName);
+
+ if (NULL == info || !(info->isUndef() || info->isDyn())) {
+ // only undefined symbol and dynamic symbol can make a reference.
+ return NULL;
+ }
+
+ return defineAndResolveSymbolForcefully(pName,
+ pIsDyn,
+ pType,
+ pDesc,
+ pBinding,
+ pSize,
+ pValue,
+ pFragmentRef,
+ pVisibility);
+}
+
+bool FragmentLinker::finalizeSymbols()
+{
+ Module::sym_iterator symbol, symEnd = m_Module.sym_end();
+ for (symbol = m_Module.sym_begin(); symbol != symEnd; ++symbol) {
+
+ if ((*symbol)->resolveInfo()->isAbsolute() ||
+ (*symbol)->resolveInfo()->type() == ResolveInfo::File) {
+ // absolute symbols or symbols with function type should have
+ // zero value
+ (*symbol)->setValue(0x0);
+ continue;
+ }
+
+ if ((*symbol)->resolveInfo()->type() == ResolveInfo::ThreadLocal) {
+ m_Backend.finalizeTLSSymbol(**symbol);
+ continue;
+ }
+
+ if ((*symbol)->hasFragRef()) {
+ // set the virtual address of the symbol. If the output file is
+ // relocatable object file, the section's virtual address becomes zero.
+ // And the symbol's value become section relative offset.
+ uint64_t value = (*symbol)->fragRef()->getOutputOffset();
+ assert(NULL != (*symbol)->fragRef()->frag());
+ uint64_t addr = (*symbol)->fragRef()->frag()->getParent()->getSection().addr();
+ (*symbol)->setValue(value + addr);
+ continue;
+ }
+ }
+
+ // finialize target-dependent symbols
+ return m_Backend.finalizeSymbols(*this);
+}
+
+bool FragmentLinker::shouldForceLocal(const ResolveInfo& pInfo) const
+{
+ // forced local symbol matches all rules:
+ // 1. We are not doing incremental linking.
+ // 2. The symbol is with Hidden or Internal visibility.
+ // 3. The symbol should be global or weak. Otherwise, local symbol is local.
+ // 4. The symbol is defined or common
+ if (LinkerConfig::Object != m_Config.codeGenType() &&
+ (pInfo.visibility() == ResolveInfo::Hidden ||
+ pInfo.visibility() == ResolveInfo::Internal) &&
+ (pInfo.isGlobal() || pInfo.isWeak()) &&
+ (pInfo.isDefine() || pInfo.isCommon()))
+ return true;
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Relocation Operations
+//===----------------------------------------------------------------------===//
+/// addRelocation - add a relocation entry in FragmentLinker (only for object file)
+///
+/// All symbols should be read and resolved before calling this function.
+Relocation* FragmentLinker::addRelocation(Relocation::Type pType,
+ LDSymbol& pSym,
+ LDSection& pSection,
+ uint32_t pOffset,
+ Relocation::Address pAddend)
+{
+ // FIXME: we should dicard sections and symbols first instead
+ // if the symbol is in the discarded input section, then we also need to
+ // discard this relocation.
+ ResolveInfo* resolve_info = pSym.resolveInfo();
+ if (!pSym.hasFragRef() &&
+ resolve_info->type() == ResolveInfo::Section &&
+ resolve_info->desc() == ResolveInfo::Undefined)
+ return NULL;
+
+ FragmentRef* frag_ref = FragmentRef::Create(*pSection.getLink(), pOffset);
+
+ Relocation* relocation = m_Backend.getRelocFactory()->produce(pType,
+ *frag_ref,
+ pAddend);
+
+ relocation->setSymInfo(resolve_info);
+ pSection.getRelocData()->getFragmentList().push_back(relocation);
+
+ return relocation;
+}
+
+bool FragmentLinker::applyRelocations()
+{
+ // when producing relocatables, no need to apply relocation
+ if (LinkerConfig::Object == m_Config.codeGenType())
+ return true;
+
+ // apply all relocations of all inputs
+ Module::obj_iterator input, inEnd = m_Module.obj_end();
+ for (input = m_Module.obj_begin(); input != inEnd; ++input) {
+ LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
+ for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
+ // bypass the reloc section if
+ // 1. its section kind is changed to Ignore. (The target section is a
+ // discarded group section.)
+ // 2. it has no reloc data. (All symbols in the input relocs are in the
+ // discarded group sections)
+ if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
+ continue;
+ RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
+ for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
+ Relocation* relocation = llvm::cast<Relocation>(reloc);
+ relocation->apply(*m_Backend.getRelocFactory());
+ } // for all relocations
+ } // for all relocation section
+ } // for all inputs
+
+ // apply relocations created by relaxation
+ BranchIslandFactory* br_factory = m_Backend.getBRIslandFactory();
+ BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
+ for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
+ BranchIsland& island = *facIter;
+ BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
+ for (iter = island.reloc_begin(); iter != iterEnd; ++iter)
+ (*iter)->apply(*m_Backend.getRelocFactory());
+ }
+ return true;
+}
+
+
+void FragmentLinker::syncRelocationResult(MemoryArea& pOutput)
+{
+ if (LinkerConfig::Object != m_Config.codeGenType())
+ normalSyncRelocationResult(pOutput);
+ else
+ partialSyncRelocationResult(pOutput);
+ return;
+}
+
+void FragmentLinker::normalSyncRelocationResult(MemoryArea& pOutput)
+{
+ MemoryRegion* region = pOutput.request(0, pOutput.handler()->size());
+
+ uint8_t* data = region->getBuffer();
+
+ // sync all relocations of all inputs
+ Module::obj_iterator input, inEnd = m_Module.obj_end();
+ for (input = m_Module.obj_begin(); input != inEnd; ++input) {
+ LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
+ for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
+ // bypass the reloc section if
+ // 1. its section kind is changed to Ignore. (The target section is a
+ // discarded group section.)
+ // 2. it has no reloc data. (All symbols in the input relocs are in the
+ // discarded group sections)
+ if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
+ continue;
+ RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
+ for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
+ Relocation* relocation = llvm::cast<Relocation>(reloc);
+
+ // bypass the relocation with NONE type. This is to avoid overwrite the
+ // target result by NONE type relocation if there is a place which has
+ // two relocations to apply to, and one of it is NONE type. The result
+ // we want is the value of the other relocation result. For example,
+ // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
+ // the same place
+ if (0x0 == relocation->type())
+ continue;
+ writeRelocationResult(*relocation, data);
+ } // for all relocations
+ } // for all relocation section
+ } // for all inputs
+
+ // sync relocations created by relaxation
+ BranchIslandFactory* br_factory = m_Backend.getBRIslandFactory();
+ BranchIslandFactory::iterator facIter, facEnd = br_factory->end();
+ for (facIter = br_factory->begin(); facIter != facEnd; ++facIter) {
+ BranchIsland& island = *facIter;
+ BranchIsland::reloc_iterator iter, iterEnd = island.reloc_end();
+ for (iter = island.reloc_begin(); iter != iterEnd; ++iter) {
+ Relocation* reloc = *iter;
+ writeRelocationResult(*reloc, data);
+ }
+ }
+
+ pOutput.clear();
+}
+
+void FragmentLinker::partialSyncRelocationResult(MemoryArea& pOutput)
+{
+ MemoryRegion* region = pOutput.request(0, pOutput.handler()->size());
+
+ uint8_t* data = region->getBuffer();
+
+ // traverse outputs' LDSection to get RelocData
+ Module::iterator sectIter, sectEnd = m_Module.end();
+ for (sectIter = m_Module.begin(); sectIter != sectEnd; ++sectIter) {
+ if (LDFileFormat::Relocation != (*sectIter)->kind())
+ continue;
+
+ RelocData* reloc_data = (*sectIter)->getRelocData();
+ RelocData::iterator relocIter, relocEnd = reloc_data->end();
+ for (relocIter = reloc_data->begin(); relocIter != relocEnd; ++relocIter) {
+ Relocation* reloc = llvm::cast<Relocation>(relocIter);
+
+ // bypass the relocation with NONE type. This is to avoid overwrite the
+ // target result by NONE type relocation if there is a place which has
+ // two relocations to apply to, and one of it is NONE type. The result
+ // we want is the value of the other relocation result. For example,
+ // in .exidx, there are usually an R_ARM_NONE and R_ARM_PREL31 apply to
+ // the same place
+ if (0x0 == reloc->type())
+ continue;
+ writeRelocationResult(*reloc, data);
+ }
+ }
+
+ pOutput.clear();
+}
+
+void FragmentLinker::writeRelocationResult(Relocation& pReloc, uint8_t* pOutput)
+{
+ // get output file offset
+ size_t out_offset = pReloc.targetRef().frag()->getParent()->getSection().offset() +
+ pReloc.targetRef().getOutputOffset();
+
+ uint8_t* target_addr = pOutput + out_offset;
+ // byte swapping if target and host has different endian, and then write back
+ if(llvm::sys::isLittleEndianHost() != m_Backend.isLittleEndian()) {
+ uint64_t tmp_data = 0;
+
+ switch(m_Backend.bitclass()) {
+ case 32u:
+ tmp_data = bswap32(pReloc.target());
+ std::memcpy(target_addr, &tmp_data, 4);
+ break;
+
+ case 64u:
+ tmp_data = bswap64(pReloc.target());
+ std::memcpy(target_addr, &tmp_data, 8);
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ std::memcpy(target_addr, &pReloc.target(), m_Backend.bitclass()/8);
+}
+
+/// isOutputPIC - return whether the output is position-independent
+bool FragmentLinker::isOutputPIC() const
+{
+ return checkIsOutputPIC();
+}
+
+/// isStaticLink - return whether we're doing static link
+bool FragmentLinker::isStaticLink() const
+{
+ return checkIsStaticLink();
+}
+
+bool FragmentLinker::checkIsOutputPIC() const
+{
+ if (LinkerConfig::DynObj == m_Config.codeGenType() ||
+ m_Config.options().isPIE())
+ return true;
+ return false;
+}
+
+bool FragmentLinker::checkIsStaticLink() const
+{
+ if (m_Module.getLibraryList().empty() && !isOutputPIC())
+ return true;
+ return false;
+}
+
diff --git a/lib/Fragment/FragmentRef.cpp b/lib/Fragment/FragmentRef.cpp
new file mode 100644
index 0000000..aec7b8c
--- /dev/null
+++ b/lib/Fragment/FragmentRef.cpp
@@ -0,0 +1,194 @@
+//===- FragmentRef.cpp --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Fragment/FragmentRef.h>
+
+#include <cstring>
+#include <cassert>
+
+#include <llvm/Support/Casting.h>
+#include <llvm/Support/ManagedStatic.h>
+
+#include <mcld/Fragment/Fragment.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/Support/GCFactory.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Fragment/Stub.h>
+
+using namespace mcld;
+
+typedef GCFactory<FragmentRef, MCLD_SECTIONS_PER_INPUT> FragRefFactory;
+
+static llvm::ManagedStatic<FragRefFactory> g_FragRefFactory;
+
+FragmentRef FragmentRef::g_NullFragmentRef;
+
+//===----------------------------------------------------------------------===//
+// FragmentRef
+//===----------------------------------------------------------------------===//
+FragmentRef::FragmentRef()
+ : m_pFragment(NULL), m_Offset(0) {
+}
+
+FragmentRef::FragmentRef(Fragment& pFrag,
+ FragmentRef::Offset pOffset)
+ : m_pFragment(&pFrag), m_Offset(pOffset) {
+}
+
+/// Create - create a fragment reference for a given fragment.
+///
+/// @param pFrag - the given fragment
+/// @param pOffset - the offset, can be larger than the fragment, but can not
+/// be larger than the section size.
+/// @return if the offset is legal, return the fragment reference. Otherwise,
+/// return NULL.
+FragmentRef* FragmentRef::Create(Fragment& pFrag, uint64_t pOffset)
+{
+ int64_t offset = pOffset;
+ Fragment* frag = &pFrag;
+
+ while (NULL != frag) {
+ offset -= frag->size();
+ if (offset <= 0)
+ break;
+ frag = frag->getNextNode();
+ }
+
+
+ if (NULL == frag)
+ return Null();
+
+ FragmentRef* result = g_FragRefFactory->allocate();
+ new (result) FragmentRef(*frag, offset + frag->size());
+
+ return result;
+}
+
+FragmentRef* FragmentRef::Create(LDSection& pSection, uint64_t pOffset)
+{
+ SectionData* data = NULL;
+ switch (pSection.kind()) {
+ case LDFileFormat::Relocation:
+ // No fragment reference refers to a relocation section
+ break;
+ case LDFileFormat::EhFrame:
+ if (pSection.hasEhFrame())
+ data = &pSection.getEhFrame()->getSectionData();
+ break;
+ default:
+ data = pSection.getSectionData();
+ break;
+ }
+
+ if (NULL == data || data->empty()) {
+ return Null();
+ }
+
+ return Create(data->front(), pOffset);
+}
+
+void FragmentRef::Clear()
+{
+ g_FragRefFactory->clear();
+}
+
+FragmentRef* FragmentRef::Null()
+{
+ return &g_NullFragmentRef;
+}
+
+FragmentRef& FragmentRef::assign(const FragmentRef& pCopy)
+{
+ m_pFragment = const_cast<Fragment*>(pCopy.m_pFragment);
+ m_Offset = pCopy.m_Offset;
+ return *this;
+}
+
+FragmentRef& FragmentRef::assign(Fragment& pFrag, FragmentRef::Offset pOffset)
+{
+ m_pFragment = &pFrag;
+ m_Offset = pOffset;
+ return *this;
+}
+
+void FragmentRef::memcpy(void* pDest, size_t pNBytes, Offset pOffset) const
+{
+ // check if the offset is still in a legal range.
+ if (NULL == m_pFragment)
+ return;
+ unsigned int total_offset = m_Offset + pOffset;
+ switch(m_pFragment->getKind()) {
+ case Fragment::Region: {
+ RegionFragment* region_frag = static_cast<RegionFragment*>(m_pFragment);
+ unsigned int total_length = region_frag->getRegion().size();
+ if (total_length < (total_offset+pNBytes))
+ pNBytes = total_length - total_offset;
+
+ std::memcpy(pDest, region_frag->getRegion().getBuffer(total_offset), pNBytes);
+ return;
+ }
+ case Fragment::Stub: {
+ Stub* stub_frag = static_cast<Stub*>(m_pFragment);
+ unsigned int total_length = stub_frag->size();
+ if (total_length < (total_offset+pNBytes))
+ pNBytes = total_length - total_offset;
+ std::memcpy(pDest, stub_frag->getContent() + total_offset, pNBytes);
+ return;
+ }
+ case Fragment::Alignment:
+ case Fragment::Fillment:
+ default:
+ return;
+ }
+}
+
+FragmentRef::Address FragmentRef::deref()
+{
+ if (NULL == m_pFragment)
+ return NULL;
+ Address base = NULL;
+ switch(m_pFragment->getKind()) {
+ case Fragment::Region:
+ base = static_cast<RegionFragment*>(m_pFragment)->getRegion().getBuffer();
+ break;
+ case Fragment::Alignment:
+ case Fragment::Fillment:
+ default:
+ return NULL;
+ }
+ return base + m_Offset;
+}
+
+FragmentRef::ConstAddress FragmentRef::deref() const
+{
+ if (NULL == m_pFragment)
+ return NULL;
+ ConstAddress base = NULL;
+ switch(m_pFragment->getKind()) {
+ case Fragment::Region:
+ base = static_cast<const RegionFragment*>(m_pFragment)->getRegion().getBuffer();
+ break;
+ case Fragment::Alignment:
+ case Fragment::Fillment:
+ default:
+ return NULL;
+ }
+ return base + m_Offset;
+}
+
+FragmentRef::Offset FragmentRef::getOutputOffset() const
+{
+ Offset result = 0;
+ if (NULL != m_pFragment)
+ result = m_pFragment->getOffset();
+ return (result + m_Offset);
+}
+
diff --git a/lib/LD/CIE.cpp b/lib/Fragment/NullFragment.cpp
similarity index 64%
copy from lib/LD/CIE.cpp
copy to lib/Fragment/NullFragment.cpp
index 5ddb166..a1d1626 100644
--- a/lib/LD/CIE.cpp
+++ b/lib/Fragment/NullFragment.cpp
@@ -1,4 +1,4 @@
-//===- CIE.cpp ------------------------------------------------------------===//
+//===- NullFragment.cpp ---------------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,18 +6,15 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/CIE.h>
+#include <mcld/Fragment/NullFragment.h>
using namespace mcld;
//===----------------------------------------------------------------------===//
-// CIE
+// NullFragment
//===----------------------------------------------------------------------===//
-CIE::CIE(MemoryRegion& pRegion, uint8_t pFDEEncode)
- : RegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
-}
-
-CIE::~CIE()
+NullFragment::NullFragment(SectionData* pSD)
+ : Fragment(Fragment::Null, pSD)
{
}
+
diff --git a/lib/LD/RegionFragment.cpp b/lib/Fragment/RegionFragment.cpp
similarity index 82%
rename from lib/LD/RegionFragment.cpp
rename to lib/Fragment/RegionFragment.cpp
index 7508ed5..363a0f2 100644
--- a/lib/LD/RegionFragment.cpp
+++ b/lib/Fragment/RegionFragment.cpp
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
-#include <mcld/LD/RegionFragment.h>
+#include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Support/MemoryRegion.h>
using namespace mcld;
@@ -22,3 +22,8 @@
{
}
+size_t RegionFragment::size() const
+{
+ return m_Region.size();
+}
+
diff --git a/lib/LD/Relocation.cpp b/lib/Fragment/Relocation.cpp
similarity index 68%
rename from lib/LD/Relocation.cpp
rename to lib/Fragment/Relocation.cpp
index 0c95e06..bae49af 100644
--- a/lib/LD/Relocation.cpp
+++ b/lib/Fragment/Relocation.cpp
@@ -6,10 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
-#include <mcld/LD/Relocation.h>
+#include <mcld/Fragment/Relocation.h>
#include <mcld/LD/RelocationFactory.h>
-#include <mcld/LD/Layout.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/SectionData.h>
#include <mcld/Support/MsgHandling.h>
using namespace mcld;
@@ -32,10 +34,10 @@
{
}
-Relocation::Address Relocation::place(const Layout& pLayout) const
+Relocation::Address Relocation::place() const
{
- Address sect_addr = pLayout.getOutputLDSection(*(m_TargetAddress.frag()))->addr();
- return sect_addr + pLayout.getOutputOffset(m_TargetAddress);
+ Address sect_addr = m_TargetAddress.frag()->getParent()->getSection().addr();
+ return sect_addr + m_TargetAddress.getOutputOffset();
}
Relocation::Address Relocation::symValue() const
@@ -47,11 +49,9 @@
return m_pSymInfo->outSymbol()->value();
}
-void Relocation::apply(RelocationFactory& pRelocFactory,
- const MCLDInfo& pLDInfo)
+void Relocation::apply(RelocationFactory& pRelocFactory)
{
- RelocationFactory::Result result =
- pRelocFactory.applyRelocation(*this, pLDInfo);
+ RelocationFactory::Result result = pRelocFactory.applyRelocation(*this);
switch (result) {
case RelocationFactory::OK: {
@@ -73,6 +73,10 @@
<< "mclinker@googlegroups.com";
return;
}
+ case RelocationFactory::Unknown: {
+ fatal(diag::unknown_relocation) << type() << symInfo()->name();
+ return;
+ }
} // end of switch
}
@@ -91,13 +95,18 @@
m_pSymInfo = pSym;
}
-Relocation::DWord& Relocation::target()
+size_t Relocation::size() const
{
- return m_TargetData;
+ // TODO: the size of Relocation fragment is handled by backend
+ return 0;
}
-const Relocation::DWord& Relocation::target() const
+void Relocation::updateAddend()
{
- return m_TargetData;
+ // Update value keep in addend if we meet a section symbol
+ if (m_pSymInfo->type() == ResolveInfo::Section) {
+ uint32_t offset = m_pSymInfo->outSymbol()->fragRef()->getOutputOffset();
+ m_Addend += offset;
+ }
}
diff --git a/lib/Fragment/Stub.cpp b/lib/Fragment/Stub.cpp
new file mode 100644
index 0000000..b7122bd
--- /dev/null
+++ b/lib/Fragment/Stub.cpp
@@ -0,0 +1,42 @@
+//===- Stub.cpp -----------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <mcld/Fragment/Stub.h>
+
+using namespace mcld;
+
+Stub::Stub()
+ : Fragment(Fragment::Stub),
+ m_pSymInfo(NULL)
+{
+}
+
+Stub::~Stub()
+{
+ for (fixup_iterator fixup= fixup_begin(); fixup != fixup_end(); ++fixup)
+ delete(*fixup);
+}
+
+void Stub::setSymInfo(ResolveInfo* pSymInfo)
+{
+ m_pSymInfo = pSymInfo;
+}
+
+void Stub::addFixup(DWord pOffset, SWord pAddend, Type pType)
+{
+ assert(pOffset < size());
+ m_FixupList.push_back(new Fixup(pOffset, pAddend, pType));
+}
+
+void Stub::addFixup(const Fixup& pFixup)
+{
+ assert(pFixup.offset() < size());
+ m_FixupList.push_back(new Fixup(pFixup));
+}
+
diff --git a/lib/LD/Android.mk b/lib/LD/Android.mk
index d3c9dd8..21e452e 100644
--- a/lib/LD/Android.mk
+++ b/lib/LD/Android.mk
@@ -5,11 +5,10 @@
# =====================================================
mcld_ld_SRC_FILES := \
- AlignFragment.cpp \
Archive.cpp \
ArchiveReader.cpp \
BranchIsland.cpp \
- CIE.cpp \
+ BranchIslandFactory.cpp \
DWARFLineInfo.cpp \
Diagnostic.cpp \
DiagnosticEngine.cpp \
@@ -22,32 +21,28 @@
ELFSegmentFactory.cpp \
EhFrame.cpp \
EhFrameHdr.cpp \
+ EhFrameReader.cpp \
ExecWriter.cpp \
- FDE.cpp \
- FillFragment.cpp \
- Fragment.cpp \
- FragmentRef.cpp \
+ GroupReader.cpp \
Layout.cpp \
LDContext.cpp \
LDFileFormat.cpp \
LDReader.cpp \
LDSection.cpp \
- LDSectionFactory.cpp \
LDSymbol.cpp \
LDWriter.cpp \
MsgHandler.cpp \
NamePool.cpp \
ObjectWriter.cpp \
- RegionFragment.cpp \
- Relocation.cpp \
+ RelocData.cpp \
RelocationFactory.cpp \
ResolveInfo.cpp \
- ResolveInfoFactory.cpp \
Resolver.cpp \
SectionData.cpp \
- SectionMap.cpp \
- SectionMerger.cpp \
+ SectionRules.cpp \
+ SectionSymbolSet.cpp \
StaticResolver.cpp \
+ StubFactory.cpp \
TextDiagnosticPrinter.cpp
# For the host
diff --git a/lib/LD/Archive.cpp b/lib/LD/Archive.cpp
index 2805541..be82922 100644
--- a/lib/LD/Archive.cpp
+++ b/lib/LD/Archive.cpp
@@ -7,8 +7,13 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/LD/Archive.h>
-#include <mcld/MC/InputFactory.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/AttributeSet.h>
+#include <mcld/MC/ContextFactory.h>
#include <llvm/ADT/StringRef.h>
+#include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/Support/MsgHandling.h>
using namespace mcld;
@@ -22,12 +27,14 @@
const char Archive::PAD[] = "\n";
const char Archive::MEMBER_MAGIC[] = "`\n";
-Archive::Archive(Input& pInputFile, InputFactory& pInputFactory)
+Archive::Archive(Input& pInputFile, InputBuilder& pBuilder)
: m_ArchiveFile(pInputFile),
m_pInputTree(NULL),
- m_SymbolFactory(32)
+ m_SymbolFactory(32),
+ m_Builder(pBuilder)
{
- m_pInputTree = new InputTree(pInputFactory);
+ // FIXME: move creation of input tree out of Archive.
+ m_pInputTree = new InputTree();
}
Archive::~Archive()
@@ -227,3 +234,41 @@
return m_StrTab;
}
+/// hasStrTable()
+bool Archive::hasStrTable() const
+{
+ return (m_StrTab.size() > 0);
+}
+
+/// getMemberFile - get the member file in an archive member
+/// @param pArchiveFile - Input reference of the archive member
+/// @param pIsThinAR - denote the archive menber is a Thin Archive or not
+/// @param pName - the name of the member file we want to get
+/// @param pPath - the path of the member file
+/// @param pFileOffset - the file offset of the member file in a regular AR
+/// FIXME: maybe we should not construct input file here
+Input* Archive::getMemberFile(Input& pArchiveFile,
+ bool isThinAR,
+ const std::string& pName,
+ const sys::fs::Path& pPath,
+ off_t pFileOffset)
+{
+ Input* member = NULL;
+ if (!isThinAR) {
+ member = m_Builder.createInput(pName, pPath, Input::Unknown, pFileOffset);
+ assert(member != NULL);
+ member->setMemArea(pArchiveFile.memArea());
+ m_Builder.setContext(*member);
+ }
+ else {
+ member = m_Builder.createInput(pName, pPath, Input::Unknown);
+ assert(member != NULL);
+ if (!m_Builder.setMemory(*member, FileHandle::ReadOnly)) {
+ error(diag::err_cannot_open_input) << member->name() << member->path();
+ return NULL;
+ }
+ m_Builder.setContext(*member);
+ }
+ return member;
+}
+
diff --git a/lib/LD/BranchIsland.cpp b/lib/LD/BranchIsland.cpp
index 7a42717..c6f5b02 100644
--- a/lib/LD/BranchIsland.cpp
+++ b/lib/LD/BranchIsland.cpp
@@ -6,10 +6,143 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "mcld/LD/BranchIsland.h"
+#include <mcld/LD/BranchIsland.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/Fragment/Stub.h>
+#include <mcld/Fragment/AlignFragment.h>
+
+#include <sstream>
using namespace mcld;
//==========================
// BranchIsland
+BranchIsland::BranchIsland(Fragment& pEntryFrag,
+ size_t pMaxSize,
+ size_t pIndex)
+ : m_Entry(pEntryFrag),
+ m_pExit(pEntryFrag.getNextNode()),
+ m_pRear(NULL),
+ m_MaxSize(pMaxSize),
+ m_Name("island-")
+{
+ // island name
+ std::ostringstream index;
+ index << pIndex;
+ m_Name.append(index.str());
+}
+
+BranchIsland::~BranchIsland()
+{
+}
+
+/// fragment iterators of the island
+SectionData::iterator BranchIsland::begin()
+{
+ return ++iterator(&m_Entry);
+}
+
+SectionData::const_iterator BranchIsland::begin() const
+{
+ return ++iterator(&m_Entry);
+}
+
+SectionData::iterator BranchIsland::end()
+{
+ if (NULL != m_pExit)
+ return iterator(m_pExit);
+ return m_Entry.getParent()->end();
+}
+
+SectionData::const_iterator BranchIsland::end() const
+{
+ if (NULL != m_pExit)
+ return iterator(m_pExit);
+ return m_Entry.getParent()->end();
+}
+
+uint64_t BranchIsland::offset() const
+{
+ return m_Entry.getOffset() + m_Entry.size();
+}
+
+size_t BranchIsland::size() const
+{
+ size_t size = 0x0;
+ if (0x0 != numOfStubs()) {
+ size = m_pRear->getOffset() + m_pRear->size() -
+ m_Entry.getNextNode()->getOffset();
+ }
+ return size;
+}
+
+size_t BranchIsland::maxSize() const
+{
+ return m_MaxSize;
+}
+
+const std::string& BranchIsland::name() const
+{
+ return m_Name;
+}
+
+size_t BranchIsland::numOfStubs() const
+{
+ return m_StubMap.numOfEntries();
+}
+
+/// findStub - return true if there is a stub built from the given prototype
+/// for the given relocation
+Stub* BranchIsland::findStub(const Stub* pPrototype, const Relocation& pReloc)
+{
+ Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend());
+ StubMapType::iterator it = m_StubMap.find(key);
+ if (it != m_StubMap.end()) {
+ assert(NULL != it.getEntry()->value());
+ return it.getEntry()->value();
+ }
+ return NULL;
+}
+
+/// addStub - add a stub into the island
+bool BranchIsland::addStub(const Stub* pPrototype,
+ const Relocation& pReloc,
+ Stub& pStub)
+{
+ bool exist = false;
+ Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend());
+ StubEntryType* entry = m_StubMap.insert(key, exist);
+ if (!exist) {
+ entry->setValue(&pStub);
+ m_pRear = &pStub;
+ SectionData* sd = m_Entry.getParent();
+
+ // insert alignment fragment
+ // TODO: check if we can reduce this alignment fragment for some cases
+ AlignFragment* align_frag = new AlignFragment(pStub.alignment(),
+ 0x0,
+ 1u,
+ pStub.alignment() - 1);
+ align_frag->setParent(sd);
+ sd->getFragmentList().insert(end(), align_frag);
+ align_frag->setOffset(align_frag->getPrevNode()->getOffset() +
+ align_frag->getPrevNode()->size());
+
+ // insert stub fragment
+ pStub.setParent(sd);
+ sd->getFragmentList().insert(end(), &pStub);
+ pStub.setOffset(pStub.getPrevNode()->getOffset() +
+ pStub.getPrevNode()->size());
+ }
+ return !exist;
+}
+
+/// addRelocation - add a relocation into island
+bool BranchIsland::addRelocation(Relocation& pReloc)
+{
+ m_Relocations.push_back(&pReloc);
+ return true;
+}
+
diff --git a/lib/LD/BranchIslandFactory.cpp b/lib/LD/BranchIslandFactory.cpp
new file mode 100644
index 0000000..6a61481
--- /dev/null
+++ b/lib/LD/BranchIslandFactory.cpp
@@ -0,0 +1,87 @@
+//===- BranchIslandFactory.cpp --------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/BranchIslandFactory.h>
+#include <mcld/Fragment/Fragment.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// BranchIslandFactory
+//===----------------------------------------------------------------------===//
+
+/// ctor
+/// @param pMaxBranchRange - the max branch range of the target backend
+/// @param pMaxIslandSize - a predifned value (1KB here) to decide the max
+/// size of the island
+BranchIslandFactory::BranchIslandFactory(uint64_t pMaxBranchRange,
+ uint64_t pMaxIslandSize)
+ : GCFactory<BranchIsland, 0>(1u), // magic number
+ m_MaxBranchRange(pMaxBranchRange - pMaxIslandSize),
+ m_MaxIslandSize(pMaxIslandSize)
+{
+}
+
+BranchIslandFactory::~BranchIslandFactory()
+{
+}
+
+/// produce - produce a island for the given fragment
+/// @param pFragment - the fragment needs a branch island
+BranchIsland* BranchIslandFactory::produce(Fragment& pFragment)
+{
+ assert(NULL == find(pFragment));
+ uint64_t island_offset = pFragment.getOffset() + m_MaxBranchRange -
+ (pFragment.getOffset() % m_MaxBranchRange);
+
+ // find out the last fragment whose offset is smaller than the calculated
+ // offset of the island
+ Fragment* frag = &pFragment;
+ while (NULL != frag->getNextNode()) {
+ if (frag->getNextNode()->getOffset() > island_offset)
+ break;
+ frag = frag->getNextNode();
+ }
+
+ // fall back one step if needed
+ if (NULL != frag &&
+ (frag->getOffset() + frag->size()) > island_offset)
+ frag = frag->getPrevNode();
+
+ // check not to break the alignment constraint in the target section
+ // (i.e., do not insert the island after a Alignment fragment)
+ while (NULL != frag &&
+ Fragment::Alignment == frag->getKind()) {
+ frag = frag->getPrevNode();
+ }
+
+ // can not find an entry fragment to bridge the island
+ if (NULL == frag)
+ return NULL;
+
+ BranchIsland *island = allocate();
+ new (island) BranchIsland(*frag, // entry fragment to the island
+ m_MaxIslandSize, // the max size of the island
+ size() - 1u); // index in the island factory
+ return island;
+}
+
+/// find - find a island for the given fragment
+/// @param pFragment - the fragment needs a branch isladn
+BranchIsland* BranchIslandFactory::find(const Fragment& pFragment)
+{
+ // Currently we always find the island in a forward direction.
+ // TODO: If we can search backward, then we may reduce the number of islands.
+ for (iterator it = begin(), ie = end(); it != ie; ++it) {
+ if ((pFragment.getOffset() < (*it).offset()) &&
+ ((pFragment.getOffset() + m_MaxBranchRange) >= (*it).offset()))
+ return &(*it);
+ }
+ return NULL;
+}
+
diff --git a/lib/LD/Diagnostic.cpp b/lib/LD/Diagnostic.cpp
index 5175ebd..786a68b 100644
--- a/lib/LD/Diagnostic.cpp
+++ b/lib/LD/Diagnostic.cpp
@@ -87,8 +87,8 @@
// skip the %.
++cur_char;
- const char* modifier = NULL, *argument = NULL;
- size_t modifier_len = 0, argument_len = 0;
+ const char* modifier = NULL;
+ size_t modifier_len = 0;
// we get a modifier
if (!isdigit(*cur_char)) {
@@ -100,7 +100,6 @@
// we get an argument
if ('{' == *cur_char) {
++cur_char; // skip '{'
- argument = cur_char;
cur_char = findMatch('}', cur_char, pEnd);
if (cur_char == pEnd) {
@@ -109,7 +108,6 @@
llvm::Twine(getID()));
}
- argument_len = cur_char - argument;
++cur_char; // skip '}'
}
}
diff --git a/lib/LD/DiagnosticEngine.cpp b/lib/LD/DiagnosticEngine.cpp
index 173b4f2..c2e52d7 100644
--- a/lib/LD/DiagnosticEngine.cpp
+++ b/lib/LD/DiagnosticEngine.cpp
@@ -9,7 +9,10 @@
#include <mcld/LD/DiagnosticEngine.h>
#include <mcld/LD/DiagnosticPrinter.h>
#include <mcld/LD/DiagnosticLineInfo.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LD/MsgHandler.h>
+#include <mcld/LinkerConfig.h>
+
+#include <cassert>
using namespace mcld;
@@ -17,7 +20,7 @@
// DiagnosticEngine
//===----------------------------------------------------------------------===//
DiagnosticEngine::DiagnosticEngine()
- : m_pLDInfo(NULL), m_pLineInfo(NULL), m_pPrinter(NULL),
+ : m_pConfig(NULL), m_pLineInfo(NULL), m_pPrinter(NULL),
m_pInfoMap(NULL), m_OwnPrinter(false) {
}
@@ -25,12 +28,15 @@
{
if (m_OwnPrinter && m_pPrinter != NULL)
delete m_pPrinter;
+
+ delete m_pInfoMap;
}
-void DiagnosticEngine::reset(const MCLDInfo& pLDInfo)
+void DiagnosticEngine::reset(const LinkerConfig& pConfig)
{
- m_pLDInfo = &pLDInfo;
- m_pInfoMap = new DiagnosticInfos(*m_pLDInfo);
+ m_pConfig = &pConfig;
+ delete m_pInfoMap;
+ m_pInfoMap = new DiagnosticInfos(*m_pConfig);
m_State.reset();
}
@@ -51,8 +57,19 @@
// emit - process current diagnostic.
bool DiagnosticEngine::emit()
{
+ assert(NULL != m_pInfoMap);
bool emitted = m_pInfoMap->process(*this);
m_State.reset();
return emitted;
}
+MsgHandler
+DiagnosticEngine::report(uint16_t pID, DiagnosticEngine::Severity pSeverity)
+{
+ m_State.ID = pID;
+ m_State.severity = pSeverity;
+
+ MsgHandler result(*this);
+ return result;
+}
+
diff --git a/lib/LD/DiagnosticInfos.cpp b/lib/LD/DiagnosticInfos.cpp
index b9a6fa9..6639d0a 100644
--- a/lib/LD/DiagnosticInfos.cpp
+++ b/lib/LD/DiagnosticInfos.cpp
@@ -10,11 +10,13 @@
#include <llvm/Support/DataTypes.h>
#include <mcld/ADT/SizeTraits.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/LD/Diagnostic.h>
#include <mcld/LD/DiagnosticInfos.h>
#include <mcld/LD/DiagnosticPrinter.h>
+#include <algorithm>
+
using namespace mcld;
namespace {
@@ -85,8 +87,9 @@
//===----------------------------------------------------------------------===//
// DiagnosticInfos
-DiagnosticInfos::DiagnosticInfos(const MCLDInfo& pLDInfo)
- : m_LDInfo(pLDInfo) {
+//===----------------------------------------------------------------------===//
+DiagnosticInfos::DiagnosticInfos(const LinkerConfig& pConfig)
+ : m_Config(pConfig) {
}
DiagnosticInfos::~DiagnosticInfos()
@@ -111,7 +114,7 @@
switch (ID) {
case diag::multiple_definitions: {
- if (m_LDInfo.options().hasMulDefs()) {
+ if (m_Config.options().hasMulDefs()) {
severity = DiagnosticEngine::Ignore;
}
break;
@@ -119,22 +122,23 @@
case diag::undefined_reference: {
// we have not implement --unresolved-symbols=method yet. So far, MCLinker
// provides the easier --allow-shlib-undefined and --no-undefined (i.e. -z defs)
- switch(m_LDInfo.output().type()) {
- case Output::Object:
- if (m_LDInfo.options().isNoUndefined())
+ switch(m_Config.codeGenType()) {
+ case LinkerConfig::Object:
+ if (m_Config.options().isNoUndefined())
severity = DiagnosticEngine::Error;
else
severity = DiagnosticEngine::Ignore;
- break;
- case Output::DynObj:
- if (m_LDInfo.options().isNoUndefined() || !m_LDInfo.options().isAllowShlibUndefined())
+ break;
+ case LinkerConfig::DynObj:
+ if (m_Config.options().isNoUndefined() || !m_Config.options().isAllowShlibUndefined())
severity = DiagnosticEngine::Error;
else
severity = DiagnosticEngine::Ignore;
- break;
- case Output::Exec:
+ break;
+ case LinkerConfig::Exec:
+ default:
severity = DiagnosticEngine::Error;
- break;
+ break;
}
break;
}
diff --git a/lib/LD/DiagnosticPrinter.cpp b/lib/LD/DiagnosticPrinter.cpp
index 7bbf473..245555f 100644
--- a/lib/LD/DiagnosticPrinter.cpp
+++ b/lib/LD/DiagnosticPrinter.cpp
@@ -28,7 +28,8 @@
{
if (pSeverity == DiagnosticEngine::Warning)
++m_NumWarnings;
- else if (pSeverity <= DiagnosticEngine::Error)
+
+ if (pSeverity <= DiagnosticEngine::Error)
++m_NumErrors;
}
diff --git a/lib/LD/ELFDynObjFileFormat.cpp b/lib/LD/ELFDynObjFileFormat.cpp
index 30183cc..9ccf967 100644
--- a/lib/LD/ELFDynObjFileFormat.cpp
+++ b/lib/LD/ELFDynObjFileFormat.cpp
@@ -6,78 +6,78 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <llvm/Support/ELF.h>
#include <mcld/LD/ELFDynObjFileFormat.h>
-#include <mcld/LD/LDFileFormat.h>
#include <mcld/LD/LDSection.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Object/ObjectBuilder.h>
+
+#include <llvm/Support/ELF.h>
using namespace mcld;
-void ELFDynObjFileFormat::initObjectType(MCLinker& pLinker)
+void ELFDynObjFileFormat::initObjectFormat(ObjectBuilder& pBuilder,
+ unsigned int pBitClass)
{
- f_pDynSymTab = &pLinker.getOrCreateOutputSectHdr(".dynsym",
+ f_pDynSymTab = pBuilder.CreateSection(".dynsym",
LDFileFormat::NamePool,
llvm::ELF::SHT_DYNSYM,
llvm::ELF::SHF_ALLOC,
- f_Backend.bitclass() / 8);
- f_pDynStrTab = &pLinker.getOrCreateOutputSectHdr(".dynstr",
+ pBitClass / 8);
+ f_pDynStrTab = pBuilder.CreateSection(".dynstr",
LDFileFormat::NamePool,
llvm::ELF::SHT_STRTAB,
llvm::ELF::SHF_ALLOC,
0x1);
- f_pInterp = &pLinker.getOrCreateOutputSectHdr(".interp",
+ f_pInterp = pBuilder.CreateSection(".interp",
LDFileFormat::Note,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC,
0x1);
- f_pHashTab = &pLinker.getOrCreateOutputSectHdr(".hash",
+ f_pHashTab = pBuilder.CreateSection(".hash",
LDFileFormat::NamePool,
llvm::ELF::SHT_HASH,
llvm::ELF::SHF_ALLOC,
- f_Backend.bitclass() / 8);
- f_pDynamic = &pLinker.getOrCreateOutputSectHdr(".dynamic",
+ pBitClass / 8);
+ f_pDynamic = pBuilder.CreateSection(".dynamic",
LDFileFormat::NamePool,
llvm::ELF::SHT_DYNAMIC,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
- f_Backend.bitclass() / 8);
- f_pRelaDyn = &pLinker.getOrCreateOutputSectHdr(".rela.dyn",
+ pBitClass / 8);
+ f_pRelaDyn = pBuilder.CreateSection(".rela.dyn",
LDFileFormat::Relocation,
llvm::ELF::SHT_RELA,
llvm::ELF::SHF_ALLOC,
- f_Backend.bitclass() / 8);
- f_pRelaPlt = &pLinker.getOrCreateOutputSectHdr(".rela.plt",
+ pBitClass / 8);
+ f_pRelaPlt = pBuilder.CreateSection(".rela.plt",
LDFileFormat::Relocation,
llvm::ELF::SHT_RELA,
llvm::ELF::SHF_ALLOC,
- f_Backend.bitclass() / 8);
- f_pRelDyn = &pLinker.getOrCreateOutputSectHdr(".rel.dyn",
+ pBitClass / 8);
+ f_pRelDyn = pBuilder.CreateSection(".rel.dyn",
LDFileFormat::Relocation,
llvm::ELF::SHT_REL,
llvm::ELF::SHF_ALLOC,
- f_Backend.bitclass() / 8);
- f_pRelPlt = &pLinker.getOrCreateOutputSectHdr(".rel.plt",
+ pBitClass / 8);
+ f_pRelPlt = pBuilder.CreateSection(".rel.plt",
LDFileFormat::Relocation,
llvm::ELF::SHT_REL,
llvm::ELF::SHF_ALLOC,
- f_Backend.bitclass() / 8);
- f_pGOT = &pLinker.getOrCreateOutputSectHdr(".got",
+ pBitClass / 8);
+ f_pGOT = pBuilder.CreateSection(".got",
LDFileFormat::Target,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
- f_Backend.bitclass() / 8);
- f_pPLT = &pLinker.getOrCreateOutputSectHdr(".plt",
+ pBitClass / 8);
+ f_pPLT = pBuilder.CreateSection(".plt",
LDFileFormat::Target,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
- f_Backend.bitclass() / 8);
- f_pGOTPLT = &pLinker.getOrCreateOutputSectHdr(".got.plt",
+ pBitClass / 8);
+ f_pGOTPLT = pBuilder.CreateSection(".got.plt",
LDFileFormat::Target,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
- f_Backend.bitclass() / 8);
- f_pEhFrameHdr = &pLinker.getOrCreateOutputSectHdr(".eh_frame_hdr",
+ pBitClass / 8);
+ f_pEhFrameHdr = pBuilder.CreateSection(".eh_frame_hdr",
LDFileFormat::EhFrameHdr,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC,
diff --git a/lib/LD/ELFDynObjReader.cpp b/lib/LD/ELFDynObjReader.cpp
index 1251656..740577c 100644
--- a/lib/LD/ELFDynObjReader.cpp
+++ b/lib/LD/ELFDynObjReader.cpp
@@ -13,7 +13,7 @@
#include <mcld/LD/ELFDynObjReader.h>
#include <mcld/LD/ELFReader.h>
#include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/Target/GNULDBackend.h>
#include <mcld/Support/MemoryRegion.h>
@@ -21,9 +21,10 @@
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// ELFDynObjReader
-ELFDynObjReader::ELFDynObjReader(GNULDBackend& pBackend, MCLinker& pLinker)
+//===----------------------------------------------------------------------===//
+ELFDynObjReader::ELFDynObjReader(GNULDBackend& pBackend, FragmentLinker& pLinker)
: DynObjReader(),
m_pELFReader(0),
m_Linker(pLinker) {
@@ -55,14 +56,14 @@
result = false;
else if (!m_pELFReader->isMyMachine(ELF_hdr))
result = false;
- else if (MCLDFile::DynObj != m_pELFReader->fileType(ELF_hdr))
+ else if (Input::DynObj != m_pELFReader->fileType(ELF_hdr))
result = false;
pInput.memArea()->release(region);
return result;
}
-/// readDSO
-bool ELFDynObjReader::readDSO(Input& pInput)
+/// readHeader
+bool ELFDynObjReader::readHeader(Input& pInput)
{
assert(pInput.hasMemArea());
@@ -71,7 +72,7 @@
hdr_size);
uint8_t* ELF_hdr = region->start();
- bool shdr_result = m_pELFReader->readSectionHeaders(pInput, m_Linker, ELF_hdr);
+ bool shdr_result = m_pELFReader->readSectionHeaders(pInput, ELF_hdr);
pInput.memArea()->release(region);
// read .dynamic to get the correct SONAME
diff --git a/lib/LD/ELFDynObjWriter.cpp b/lib/LD/ELFDynObjWriter.cpp
index cabc9e9..48ce0a3 100644
--- a/lib/LD/ELFDynObjWriter.cpp
+++ b/lib/LD/ELFDynObjWriter.cpp
@@ -7,25 +7,28 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/LD/ELFDynObjWriter.h>
+
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/LD/LDSymbol.h>
#include <mcld/Target/GNULDBackend.h>
#include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Support/MemoryArea.h>
+
#include <llvm/Support/ELF.h>
+
#include <vector>
using namespace llvm;
using namespace mcld;
-
-//==========================
+//===----------------------------------------------------------------------===//
// ELFDynObjWriter
-ELFDynObjWriter::ELFDynObjWriter(GNULDBackend& pBackend, MCLinker& pLinker)
+//===----------------------------------------------------------------------===//
+ELFDynObjWriter::ELFDynObjWriter(GNULDBackend& pBackend, FragmentLinker& pLinker)
: DynObjWriter(pBackend),
ELFWriter(pBackend),
- m_Backend(pBackend),
m_Linker(pLinker) {
}
@@ -34,41 +37,34 @@
{
}
-llvm::error_code ELFDynObjWriter::writeDynObj(Output& pOutput)
+llvm::error_code ELFDynObjWriter::writeDynObj(Module& pModule,
+ MemoryArea& pOutput)
{
+ target().emitInterp(pOutput);
+
// Write out name pool sections: .dynsym, .dynstr, .hash
- target().emitDynNamePools(pOutput,
- m_Linker.getOutputSymbols(),
- m_Linker.getLayout(),
- m_Linker.getLDInfo());
+ target().emitDynNamePools(pModule, pOutput);
// Write out name pool sections: .symtab, .strtab
- target().emitRegNamePools(pOutput,
- m_Linker.getOutputSymbols(),
- m_Linker.getLayout(),
- m_Linker.getLDInfo());
+ target().emitRegNamePools(pModule, pOutput);
// Write out regular ELF sections
- unsigned int secIdx = 0;
- unsigned int secEnd = pOutput.context()->numOfSections();
- for (secIdx = 0; secIdx < secEnd; ++secIdx) {
- LDSection* sect = pOutput.context()->getSection(secIdx);
+ Module::iterator sect, sectEnd = pModule.end();
+ for (sect = pModule.begin(); sect != sectEnd; ++sect) {
MemoryRegion* region = NULL;
// request output region
- switch(sect->kind()) {
+ switch((*sect)->kind()) {
case LDFileFormat::Regular:
case LDFileFormat::Relocation:
case LDFileFormat::Target:
case LDFileFormat::Debug:
case LDFileFormat::GCCExceptTable:
case LDFileFormat::EhFrame: {
- region = pOutput.memArea()->request(sect->offset(), sect->size());
+ region = pOutput.request((*sect)->offset(), (*sect)->size());
if (NULL == region) {
- llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section[") +
- llvm::Twine(secIdx) +
- llvm::Twine("] - `") +
- sect->name() +
- llvm::Twine("'.\n"));
+ llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section ") +
+ llvm::Twine((*sect)->name()) +
+ llvm::Twine(".\n"));
}
break;
}
@@ -79,38 +75,35 @@
case LDFileFormat::MetaData:
case LDFileFormat::Version:
case LDFileFormat::EhFrameHdr:
+ case LDFileFormat::StackNote:
// ignore these sections
continue;
default: {
llvm::errs() << "WARNING: unsupported section kind: "
- << sect->kind()
+ << (*sect)->kind()
<< " of section "
- << sect->name()
+ << (*sect)->name()
<< ".\n";
continue;
}
}
// write out sections with data
- switch(sect->kind()) {
+ switch((*sect)->kind()) {
case LDFileFormat::Regular:
case LDFileFormat::Debug:
case LDFileFormat::GCCExceptTable:
case LDFileFormat::EhFrame: {
// FIXME: if optimization of exception handling sections is enabled,
// then we should emit these sections by the other way.
- emitSectionData(m_Linker.getLayout(), *sect, *region);
+ emitSectionData(**sect, *region);
break;
}
case LDFileFormat::Relocation:
- emitRelocation(m_Linker.getLayout(), pOutput, *sect, *region);
+ emitRelocation(m_Linker.getLDInfo(), **sect, *region);
break;
case LDFileFormat::Target:
- target().emitSectionData(pOutput,
- *sect,
- m_Linker.getLDInfo(),
- m_Linker.getLayout(),
- *region);
+ target().emitSectionData(**sect, *region);
break;
default:
continue;
@@ -118,37 +111,35 @@
} // end of for loop
+ emitELFShStrTab(target().getOutputFormat()->getShStrTab(),
+ pModule,
+ pOutput);
+
if (32 == target().bitclass()) {
// Write out ELF header
// Write out section header table
- emitELF32ShStrTab(pOutput, m_Linker);
-
writeELF32Header(m_Linker.getLDInfo(),
- m_Linker.getLayout(),
- target(),
+ pModule,
pOutput);
- emitELF32ProgramHeader(pOutput, target());
+ emitELF32ProgramHeader(pOutput);
- emitELF32SectionHeader(pOutput, m_Linker);
+ emitELF32SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
}
else if (64 == target().bitclass()) {
// Write out ELF header
// Write out section header table
- emitELF64ShStrTab(pOutput, m_Linker);
-
writeELF64Header(m_Linker.getLDInfo(),
- m_Linker.getLayout(),
- target(),
+ pModule,
pOutput);
- emitELF64ProgramHeader(pOutput, target());
+ emitELF64ProgramHeader(pOutput);
- emitELF64SectionHeader(pOutput, m_Linker);
+ emitELF64SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
}
else
return make_error_code(errc::not_supported);
- pOutput.memArea()->clear();
+ pOutput.clear();
return llvm::make_error_code(llvm::errc::success);
}
diff --git a/lib/LD/ELFExecFileFormat.cpp b/lib/LD/ELFExecFileFormat.cpp
index 8ae0de0..a05c058 100644
--- a/lib/LD/ELFExecFileFormat.cpp
+++ b/lib/LD/ELFExecFileFormat.cpp
@@ -6,81 +6,81 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <llvm/Support/ELF.h>
#include <mcld/LD/ELFExecFileFormat.h>
-#include <mcld/LD/LDFileFormat.h>
#include <mcld/LD/LDSection.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Object/ObjectBuilder.h>
+
+#include <llvm/Support/ELF.h>
using namespace mcld;
-void ELFExecFileFormat::initObjectType(MCLinker& pLinker)
+void ELFExecFileFormat::initObjectFormat(ObjectBuilder& pBuilder,
+ unsigned int pBitClass)
{
// FIXME: make sure ELF executable files has these sections.
- f_pDynSymTab = &pLinker.getOrCreateOutputSectHdr(".dynsym",
+ f_pDynSymTab = pBuilder.CreateSection(".dynsym",
LDFileFormat::NamePool,
llvm::ELF::SHT_DYNSYM,
llvm::ELF::SHF_ALLOC,
- f_Backend.bitclass() / 8);
- f_pDynStrTab = &pLinker.getOrCreateOutputSectHdr(".dynstr",
+ pBitClass / 8);
+ f_pDynStrTab = pBuilder.CreateSection(".dynstr",
LDFileFormat::NamePool,
llvm::ELF::SHT_STRTAB,
llvm::ELF::SHF_ALLOC,
0x1);
- f_pInterp = &pLinker.getOrCreateOutputSectHdr(".interp",
+ f_pInterp = pBuilder.CreateSection(".interp",
LDFileFormat::Note,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC,
0x1);
- f_pHashTab = &pLinker.getOrCreateOutputSectHdr(".hash",
+ f_pHashTab = pBuilder.CreateSection(".hash",
LDFileFormat::NamePool,
llvm::ELF::SHT_HASH,
llvm::ELF::SHF_ALLOC,
- f_Backend.bitclass() / 8);
- f_pDynamic = &pLinker.getOrCreateOutputSectHdr(".dynamic",
+ pBitClass / 8);
+ f_pDynamic = pBuilder.CreateSection(".dynamic",
LDFileFormat::NamePool,
llvm::ELF::SHT_DYNAMIC,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
- f_Backend.bitclass() / 8);
- f_pRelaDyn = &pLinker.getOrCreateOutputSectHdr(".rela.dyn",
+ pBitClass / 8);
+ f_pRelaDyn = pBuilder.CreateSection(".rela.dyn",
LDFileFormat::Relocation,
llvm::ELF::SHT_RELA,
llvm::ELF::SHF_ALLOC,
- f_Backend.bitclass() / 8);
- f_pRelaPlt = &pLinker.getOrCreateOutputSectHdr(".rela.plt",
+ pBitClass / 8);
+ f_pRelaPlt = pBuilder.CreateSection(".rela.plt",
LDFileFormat::Relocation,
llvm::ELF::SHT_RELA,
llvm::ELF::SHF_ALLOC,
- f_Backend.bitclass() / 8);
- f_pRelDyn = &pLinker.getOrCreateOutputSectHdr(".rel.dyn",
+ pBitClass / 8);
+ f_pRelDyn = pBuilder.CreateSection(".rel.dyn",
LDFileFormat::Relocation,
llvm::ELF::SHT_REL,
llvm::ELF::SHF_ALLOC,
- f_Backend.bitclass() / 8);
- f_pRelPlt = &pLinker.getOrCreateOutputSectHdr(".rel.plt",
+ pBitClass / 8);
+ f_pRelPlt = pBuilder.CreateSection(".rel.plt",
LDFileFormat::Relocation,
llvm::ELF::SHT_REL,
llvm::ELF::SHF_ALLOC,
- f_Backend.bitclass() / 8);
- f_pGOT = &pLinker.getOrCreateOutputSectHdr(".got",
+ pBitClass / 8);
+ f_pGOT = pBuilder.CreateSection(".got",
LDFileFormat::Target,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
- f_Backend.bitclass() / 8);
- f_pPLT = &pLinker.getOrCreateOutputSectHdr(".plt",
+ pBitClass / 8);
+ f_pPLT = pBuilder.CreateSection(".plt",
LDFileFormat::Target,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
- f_Backend.bitclass() / 8);
- f_pGOTPLT = &pLinker.getOrCreateOutputSectHdr(".got.plt",
+ pBitClass / 8);
+ f_pGOTPLT = pBuilder.CreateSection(".got.plt",
LDFileFormat::Target,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
- f_Backend.bitclass() / 8);
- f_pEhFrameHdr = &pLinker.getOrCreateOutputSectHdr(".eh_frame_hdr",
- LDFileFormat::EhFrameHdr,
- llvm::ELF::SHT_PROGBITS,
- llvm::ELF::SHF_ALLOC,
- 0x4);
+ pBitClass / 8);
+ f_pEhFrameHdr = pBuilder.CreateSection(".eh_frame_hdr",
+ LDFileFormat::EhFrameHdr,
+ llvm::ELF::SHT_PROGBITS,
+ llvm::ELF::SHF_ALLOC,
+ 0x4);
}
diff --git a/lib/LD/ELFExecWriter.cpp b/lib/LD/ELFExecWriter.cpp
index 7438180..dec5e26 100644
--- a/lib/LD/ELFExecWriter.cpp
+++ b/lib/LD/ELFExecWriter.cpp
@@ -7,12 +7,14 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/LD/ELFExecWriter.h>
+
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/LD/LDSymbol.h>
#include <mcld/Target/GNULDBackend.h>
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Support/MemoryArea.h>
+
#include <llvm/Support/ELF.h>
#include <vector>
@@ -20,12 +22,12 @@
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// ELFExecWriter
-ELFExecWriter::ELFExecWriter(GNULDBackend& pBackend, MCLinker& pLinker)
+//===----------------------------------------------------------------------===//
+ELFExecWriter::ELFExecWriter(GNULDBackend& pBackend, FragmentLinker& pLinker)
: ExecWriter(pBackend),
ELFWriter(pBackend),
- m_Backend(pBackend),
m_Linker(pLinker) {
}
@@ -34,43 +36,34 @@
{
}
-llvm::error_code ELFExecWriter::writeExecutable(Output& pOutput)
+llvm::error_code ELFExecWriter::writeExecutable(Module& pModule,
+ MemoryArea& pOutput)
{
// write out the interpreter section: .interp
- target().emitInterp(pOutput, m_Linker.getLDInfo());
+ target().emitInterp(pOutput);
// Write out name pool sections: .dynsym, .dynstr, .hash
- target().emitDynNamePools(pOutput,
- m_Linker.getOutputSymbols(),
- m_Linker.getLayout(),
- m_Linker.getLDInfo());
+ target().emitDynNamePools(pModule, pOutput);
// Write out name pool sections: .symtab, .strtab
- target().emitRegNamePools(pOutput,
- m_Linker.getOutputSymbols(),
- m_Linker.getLayout(),
- m_Linker.getLDInfo());
+ target().emitRegNamePools(pModule, pOutput);
// Write out regular ELF sections
- unsigned int secIdx = 0;
- unsigned int secEnd = pOutput.context()->numOfSections();
- for (secIdx = 0; secIdx < secEnd; ++secIdx) {
- LDSection* sect = pOutput.context()->getSection(secIdx);
+ Module::iterator sect, sectEnd = pModule.end();
+ for (sect = pModule.begin(); sect != sectEnd; ++sect) {
MemoryRegion* region = NULL;
// request output region
- switch(sect->kind()) {
+ switch((*sect)->kind()) {
case LDFileFormat::Regular:
case LDFileFormat::Relocation:
case LDFileFormat::Target:
case LDFileFormat::Debug:
case LDFileFormat::GCCExceptTable:
case LDFileFormat::EhFrame: {
- region = pOutput.memArea()->request(sect->offset(), sect->size());
+ region = pOutput.request((*sect)->offset(), (*sect)->size());
if (NULL == region) {
- llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section[") +
- llvm::Twine(secIdx) +
- llvm::Twine("] - `") +
- sect->name() +
+ llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section `") +
+ llvm::Twine((*sect)->name()) +
llvm::Twine("'.\n"));
}
break;
@@ -82,76 +75,71 @@
case LDFileFormat::MetaData:
case LDFileFormat::Version:
case LDFileFormat::EhFrameHdr:
+ case LDFileFormat::StackNote:
// ignore these sections
continue;
default: {
llvm::errs() << "WARNING: unsupported section kind: "
- << sect->kind()
+ << (*sect)->kind()
<< " of section "
- << sect->name()
+ << (*sect)->name()
<< ".\n";
continue;
}
}
// write out sections with data
- switch(sect->kind()) {
+ switch((*sect)->kind()) {
case LDFileFormat::Regular:
case LDFileFormat::Debug:
case LDFileFormat::GCCExceptTable:
case LDFileFormat::EhFrame: {
// FIXME: if optimization of exception handling sections is enabled,
// then we should emit these sections by the other way.
- emitSectionData(m_Linker.getLayout(), *sect, *region);
+ emitSectionData(**sect, *region);
break;
}
case LDFileFormat::Relocation:
- emitRelocation(m_Linker.getLayout(), pOutput, *sect, *region);
+ emitRelocation(m_Linker.getLDInfo(), **sect, *region);
break;
case LDFileFormat::Target:
- target().emitSectionData(pOutput,
- *sect,
- m_Linker.getLDInfo(),
- m_Linker.getLayout(),
- *region);
+ target().emitSectionData(**sect, *region);
break;
default:
continue;
}
} // end of for loop
+ emitELFShStrTab(target().getOutputFormat()->getShStrTab(),
+ pModule,
+ pOutput);
+
if (32 == target().bitclass()) {
// Write out ELF header
// Write out section header table
- emitELF32ShStrTab(pOutput, m_Linker);
-
writeELF32Header(m_Linker.getLDInfo(),
- m_Linker.getLayout(),
- target(),
+ pModule,
pOutput);
- emitELF32ProgramHeader(pOutput, target());
+ emitELF32ProgramHeader(pOutput);
- emitELF32SectionHeader(pOutput, m_Linker);
+ emitELF32SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
}
else if (64 == target().bitclass()) {
// Write out ELF header
// Write out section header table
- emitELF64ShStrTab(pOutput, m_Linker);
-
writeELF64Header(m_Linker.getLDInfo(),
- m_Linker.getLayout(),
- target(),
+ pModule,
pOutput);
- emitELF64ProgramHeader(pOutput, target());
+ emitELF64ProgramHeader(pOutput);
- emitELF64SectionHeader(pOutput, m_Linker);
+ emitELF64SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
}
else
return make_error_code(errc::not_supported);
- pOutput.memArea()->clear();
+ pOutput.clear();
return llvm::make_error_code(llvm::errc::success);
}
diff --git a/lib/LD/ELFFileFormat.cpp b/lib/LD/ELFFileFormat.cpp
index f1c39cb..7512e38 100644
--- a/lib/LD/ELFFileFormat.cpp
+++ b/lib/LD/ELFFileFormat.cpp
@@ -7,16 +7,15 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/LD/ELFFileFormat.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/MC/MCLDFile.h>
-#include <llvm/Support/ELF.h>
+#include <mcld/Object/ObjectBuilder.h>
#include <mcld/Target/GNULDBackend.h>
+#include <llvm/Support/ELF.h>
+
using namespace mcld;
-ELFFileFormat::ELFFileFormat(GNULDBackend& pBackend)
- : f_Backend(pBackend),
- f_pNULLSection(NULL),
+ELFFileFormat::ELFFileFormat()
+ : f_pNULLSection(NULL),
f_pGOT(NULL),
f_pPLT(NULL),
f_pRelDyn(NULL),
@@ -58,94 +57,92 @@
f_pNoteABITag(NULL),
f_pStab(NULL),
f_pStabStr(NULL),
- f_pStack(NULL) {
+ f_pStack(NULL),
+ f_pStackNote(NULL),
+ f_pDataRelRoLocal(NULL) {
}
-ELFFileFormat::~ELFFileFormat()
+void ELFFileFormat::initStdSections(ObjectBuilder& pBuilder, unsigned int pBitClass)
{
-}
-
-void ELFFileFormat::initObjectFormat(MCLinker& pLinker)
-{
- f_pTextSection = &pLinker.getOrCreateOutputSectHdr(".text",
+ f_pTextSection = pBuilder.CreateSection(".text",
LDFileFormat::Regular,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
0x1);
- f_pNULLSection = &pLinker.getOrCreateOutputSectHdr("",
+ f_pNULLSection = pBuilder.CreateSection("",
LDFileFormat::Null,
llvm::ELF::SHT_NULL,
0x0);
- f_pReadOnlySection = &pLinker.getOrCreateOutputSectHdr(".rodata",
+ f_pReadOnlySection = pBuilder.CreateSection(".rodata",
LDFileFormat::Regular,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC,
0x1);
- f_pBSSSection = &pLinker.getOrCreateOutputSectHdr(".bss",
+ f_pBSSSection = pBuilder.CreateSection(".bss",
LDFileFormat::BSS,
llvm::ELF::SHT_NOBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
0x1);
- f_pComment = &pLinker.getOrCreateOutputSectHdr(".comment",
+ f_pComment = pBuilder.CreateSection(".comment",
LDFileFormat::MetaData,
llvm::ELF::SHT_PROGBITS,
0x0,
0x1);
- f_pDataSection = &pLinker.getOrCreateOutputSectHdr(".data",
+ f_pDataSection = pBuilder.CreateSection(".data",
LDFileFormat::Regular,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
0x1);
- f_pData1 = &pLinker.getOrCreateOutputSectHdr(".data1",
+ f_pData1 = pBuilder.CreateSection(".data1",
LDFileFormat::Regular,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
0x1);
- f_pDebug = &pLinker.getOrCreateOutputSectHdr(".debug",
+ f_pDebug = pBuilder.CreateSection(".debug",
LDFileFormat::Debug,
llvm::ELF::SHT_PROGBITS,
0x0,
0x1);
- f_pInit = &pLinker.getOrCreateOutputSectHdr(".init",
+ f_pInit = pBuilder.CreateSection(".init",
LDFileFormat::Regular,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
0x1);
- f_pInitArray = &pLinker.getOrCreateOutputSectHdr(".init_array",
+ f_pInitArray = pBuilder.CreateSection(".init_array",
LDFileFormat::Regular,
llvm::ELF::SHT_INIT_ARRAY,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
0x1);
- f_pFini = &pLinker.getOrCreateOutputSectHdr(".fini",
+ f_pFini = pBuilder.CreateSection(".fini",
LDFileFormat::Regular,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
0x1);
- f_pFiniArray = &pLinker.getOrCreateOutputSectHdr(".fini_array",
+ f_pFiniArray = pBuilder.CreateSection(".fini_array",
LDFileFormat::Regular,
llvm::ELF::SHT_FINI_ARRAY,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
0x1);
- f_pLine = &pLinker.getOrCreateOutputSectHdr(".line",
+ f_pLine = pBuilder.CreateSection(".line",
LDFileFormat::Debug,
llvm::ELF::SHT_PROGBITS,
0x0,
0x1);
- f_pPreInitArray = &pLinker.getOrCreateOutputSectHdr(".preinit_array",
+ f_pPreInitArray = pBuilder.CreateSection(".preinit_array",
LDFileFormat::Regular,
llvm::ELF::SHT_PREINIT_ARRAY,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
0x1);
// the definition of SHF_XXX attributes of rodata in Linux Standard Base
// conflicts with System V standard. We follow System V standard.
- f_pROData1 = &pLinker.getOrCreateOutputSectHdr(".rodata1",
+ f_pROData1 = pBuilder.CreateSection(".rodata1",
LDFileFormat::Regular,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC,
0x1);
- f_pShStrTab = &pLinker.getOrCreateOutputSectHdr(".shstrtab",
+ f_pShStrTab = pBuilder.CreateSection(".shstrtab",
LDFileFormat::NamePool,
llvm::ELF::SHT_STRTAB,
0x0,
@@ -153,24 +150,24 @@
// In ELF Spec Book I, p1-16. If symbol table and string table are in
// loadable segments, set the attribute to SHF_ALLOC bit. But in the
// real world, this bit always turn off.
- f_pSymTab = &pLinker.getOrCreateOutputSectHdr(".symtab",
+ f_pSymTab = pBuilder.CreateSection(".symtab",
LDFileFormat::NamePool,
llvm::ELF::SHT_SYMTAB,
0x0,
- f_Backend.bitclass() / 8);
- f_pStrTab = &pLinker.getOrCreateOutputSectHdr(".strtab",
+ pBitClass / 8);
+ f_pStrTab = pBuilder.CreateSection(".strtab",
LDFileFormat::NamePool,
llvm::ELF::SHT_STRTAB,
0x0,
0x1);
- f_pTBSS = &pLinker.getOrCreateOutputSectHdr(".tbss",
+ f_pTBSS = pBuilder.CreateSection(".tbss",
LDFileFormat::BSS,
llvm::ELF::SHT_NOBITS,
llvm::ELF::SHF_ALLOC |
llvm::ELF::SHF_WRITE |
llvm::ELF::SHF_TLS,
0x1);
- f_pTData = &pLinker.getOrCreateOutputSectHdr(".tdata",
+ f_pTData = pBuilder.CreateSection(".tdata",
LDFileFormat::Regular,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC |
@@ -179,60 +176,75 @@
0x1);
/// @ref 10.3.1.2, ISO/IEC 23360, Part 1:2010(E), p. 24.
- f_pCtors = &pLinker.getOrCreateOutputSectHdr(".ctor",
+ f_pCtors = pBuilder.CreateSection(".ctors",
LDFileFormat::Regular,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
0x1);
- f_pDataRelRo = &pLinker.getOrCreateOutputSectHdr(".data.rel.ro",
+ f_pDataRelRo = pBuilder.CreateSection(".data.rel.ro",
LDFileFormat::Regular,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
0x1);
- f_pDtors = &pLinker.getOrCreateOutputSectHdr(".dtors",
+ f_pDtors = pBuilder.CreateSection(".dtors",
LDFileFormat::Regular,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
0x1);
- f_pEhFrame = &pLinker.getOrCreateOutputSectHdr(".eh_frame",
+ f_pEhFrame = pBuilder.CreateSection(".eh_frame",
LDFileFormat::EhFrame,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC,
0x4);
- f_pGCCExceptTable = &pLinker.getOrCreateOutputSectHdr(".gcc_except_table",
+ f_pGCCExceptTable = pBuilder.CreateSection(".gcc_except_table",
LDFileFormat::GCCExceptTable,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC,
0x4);
- f_pGNUVersion = &pLinker.getOrCreateOutputSectHdr(".gnu.version",
+ f_pGNUVersion = pBuilder.CreateSection(".gnu.version",
LDFileFormat::Version,
llvm::ELF::SHT_GNU_versym,
llvm::ELF::SHF_ALLOC,
0x1);
- f_pGNUVersionD = &pLinker.getOrCreateOutputSectHdr(".gnu.version_d",
+ f_pGNUVersionD = pBuilder.CreateSection(".gnu.version_d",
LDFileFormat::Version,
llvm::ELF::SHT_GNU_verdef,
llvm::ELF::SHF_ALLOC,
0x1);
- f_pGNUVersionR = &pLinker.getOrCreateOutputSectHdr(".gnu.version_r",
+ f_pGNUVersionR = pBuilder.CreateSection(".gnu.version_r",
LDFileFormat::Version,
llvm::ELF::SHT_GNU_verneed,
llvm::ELF::SHF_ALLOC,
0x1);
- f_pJCR = &pLinker.getOrCreateOutputSectHdr(".jcr",
+ f_pJCR = pBuilder.CreateSection(".jcr",
LDFileFormat::Regular,
llvm::ELF::SHT_PROGBITS,
llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
0x1);
- f_pStab = &pLinker.getOrCreateOutputSectHdr(".stab",
+ f_pStab = pBuilder.CreateSection(".stab",
LDFileFormat::Debug,
llvm::ELF::SHT_PROGBITS,
0x0,
0x1);
- f_pStabStr = &pLinker.getOrCreateOutputSectHdr(".stabstr",
+ f_pStabStr = pBuilder.CreateSection(".stabstr",
LDFileFormat::Debug,
llvm::ELF::SHT_STRTAB,
0x0,
0x1);
+ f_pStackNote = pBuilder.CreateSection(".note.GNU-stack",
+ LDFileFormat::StackNote,
+ llvm::ELF::SHT_PROGBITS,
+ 0x0,
+ 0x1);
+
+ /// @ref GCC convention, see http://www.airs.com/blog/archives/189
+ f_pDataRelRoLocal = pBuilder.CreateSection(".data.rel.ro.local",
+ LDFileFormat::Regular,
+ llvm::ELF::SHT_PROGBITS,
+ llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
+ 0x1);
+ /// Initialize format dependent sections. (sections for executable and shared
+ /// objects)
+ initObjectFormat(pBuilder, pBitClass);
}
diff --git a/lib/LD/ELFObjectReader.cpp b/lib/LD/ELFObjectReader.cpp
index e645567..4124098 100644
--- a/lib/LD/ELFObjectReader.cpp
+++ b/lib/LD/ELFObjectReader.cpp
@@ -6,6 +6,7 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+#include <mcld/LD/ELFObjectReader.h>
#include <string>
#include <cassert>
@@ -13,33 +14,41 @@
#include <llvm/Support/ELF.h>
#include <llvm/ADT/Twine.h>
+#include <mcld/IRBuilder.h>
#include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/LD/RegionFragment.h>
+#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/LD/ELFReader.h>
-#include <mcld/LD/ELFObjectReader.h>
+#include <mcld/LD/EhFrameReader.h>
+#include <mcld/LD/EhFrame.h>
#include <mcld/Target/GNULDBackend.h>
#include <mcld/Support/MsgHandling.h>
+#include <mcld/Object/ObjectBuilder.h>
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// ELFObjectReader
+//===----------------------------------------------------------------------===//
/// constructor
-ELFObjectReader::ELFObjectReader(GNULDBackend& pBackend, MCLinker& pLinker)
+ELFObjectReader::ELFObjectReader(GNULDBackend& pBackend, FragmentLinker& pLinker)
: ObjectReader(),
- m_pELFReader(0),
- m_Linker(pLinker)
-{
+ m_pELFReader(NULL),
+ m_pEhFrameReader(NULL),
+ m_Linker(pLinker),
+ m_ReadFlag(ParseEhFrame),
+ m_Backend(pBackend) {
if (32 == pBackend.bitclass() && pBackend.isLittleEndian()) {
m_pELFReader = new ELFReader<32, true>(pBackend);
}
+
+ m_pEhFrameReader = new EhFrameReader();
}
/// destructor
ELFObjectReader::~ELFObjectReader()
{
delete m_pELFReader;
+ delete m_pEhFrameReader;
}
/// isMyFormat
@@ -61,14 +70,14 @@
result = false;
else if (!m_pELFReader->isMyMachine(ELF_hdr))
result = false;
- else if (MCLDFile::Object != m_pELFReader->fileType(ELF_hdr))
+ else if (Input::Object != m_pELFReader->fileType(ELF_hdr))
result = false;
pInput.memArea()->release(region);
return result;
}
-/// readObject - read section header and create LDSections.
-bool ELFObjectReader::readObject(Input& pInput)
+/// readHeader - read section header and create LDSections.
+bool ELFObjectReader::readHeader(Input& pInput)
{
assert(pInput.hasMemArea());
@@ -76,7 +85,7 @@
MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
hdr_size);
uint8_t* ELF_hdr = region->start();
- bool result = m_pELFReader->readSectionHeaders(pInput, m_Linker, ELF_hdr);
+ bool result = m_pELFReader->readSectionHeaders(pInput, ELF_hdr);
pInput.memArea()->release(region);
return result;
}
@@ -96,13 +105,12 @@
case LDFileFormat::Group: {
assert(NULL != (*section)->getLink());
ResolveInfo* signature =
- m_pELFReader->readSymbol(pInput,
- *(*section)->getLink(),
- m_Linker.getLDInfo(),
- (*section)->getInfo());
+ m_pELFReader->readSignature(pInput,
+ *(*section)->getLink(),
+ (*section)->getInfo());
bool exist = false;
- if (0 == std::strlen(signature->name()) &&
+ if (0 == signature->nameSize() &&
ResolveInfo::Section == signature->type()) {
// if the signature is a section symbol in input object, we use the
// section name as group signature.
@@ -113,7 +121,7 @@
if (exist) {
// if this is not the first time we see this group signature, then
- // ignore all the members in this group (set NULL)
+ // ignore all the members in this group (set Ignore)
MemoryRegion* region = pInput.memArea()->request(
pInput.fileOffset() + (*section)->offset(), (*section)->size());
llvm::ELF::Elf32_Word* value =
@@ -121,75 +129,93 @@
size_t size = region->size() / sizeof(llvm::ELF::Elf32_Word);
if (llvm::ELF::GRP_COMDAT == *value) {
- for (size_t index = 1; index < size; ++index)
- pInput.context()->getSectionTable()[value[index]] = NULL;
+ for (size_t index = 1; index < size; ++index) {
+ pInput.context()->getSection(value[index])->setKind(LDFileFormat::Ignore);
+ }
}
pInput.memArea()->release(region);
}
+ ResolveInfo::Destroy(signature);
break;
}
/** relocation sections **/
case LDFileFormat::Relocation: {
assert(NULL != (*section)->getLink());
size_t link_index = (*section)->getLink()->index();
- if (NULL == pInput.context()->getSectionTable()[link_index]) {
+ LDSection* link_sect = pInput.context()->getSection(link_index);
+ if (NULL == link_sect || LDFileFormat::Ignore == link_sect->kind()) {
// Relocation sections of group members should also be part of the
// group. Thus, if the associated member sections are ignored, the
// related relocations should be also ignored.
- *section = NULL;
+ (*section)->setKind(LDFileFormat::Ignore);
}
break;
}
/** normal sections **/
- // FIXME: support Version Kinds
+ // FIXME: support Version Kind
case LDFileFormat::Version:
+ // FIXME: support GCCExceptTable Kind
+ case LDFileFormat::GCCExceptTable:
/** Fall through **/
case LDFileFormat::Regular:
case LDFileFormat::Note:
- case LDFileFormat::Debug:
case LDFileFormat::MetaData: {
- if (!m_pELFReader->readRegularSection(pInput, m_Linker, **section))
+ SectionData* sd = IRBuilder::CreateSectionData(**section);
+ if (!m_pELFReader->readRegularSection(pInput, *sd))
fatal(diag::err_cannot_read_section) << (*section)->name();
break;
}
+ case LDFileFormat::Debug: {
+ if (m_Linker.getLDInfo().options().stripDebug()) {
+ (*section)->setKind(LDFileFormat::Ignore);
+ }
+ else {
+ SectionData* sd = IRBuilder::CreateSectionData(**section);
+ if (!m_pELFReader->readRegularSection(pInput, *sd)) {
+ fatal(diag::err_cannot_read_section) << (*section)->name();
+ }
+ }
+ break;
+ }
case LDFileFormat::EhFrame: {
- if (!m_pELFReader->readEhFrame(pInput, m_Linker, **section))
- fatal(diag::err_cannot_read_section) <<(*section)->name();
- break;
- }
- case LDFileFormat::GCCExceptTable: {
- //if (!m_pELFReader->readExceptionSection(pInput, m_Linker, **section))
- if (!m_pELFReader->readRegularSection(pInput, m_Linker, **section))
- fatal(diag::err_cannot_read_section) << (*section)->name();
+ EhFrame* eh_frame = IRBuilder::CreateEhFrame(**section);
+
+ if (m_Linker.getLDInfo().options().hasEhFrameHdr() &&
+ (m_ReadFlag & ParseEhFrame)) {
+
+ // if --eh-frame-hdr option is given, parse .eh_frame.
+ if (!m_pEhFrameReader->read<32, true>(pInput, *eh_frame)) {
+ // if we failed to parse a .eh_frame, we should not parse the rest
+ // .eh_frame.
+ m_ReadFlag ^= ParseEhFrame;
+ }
+ }
+ else {
+ if (!m_pELFReader->readRegularSection(pInput,
+ eh_frame->getSectionData())) {
+ fatal(diag::err_cannot_read_section) << (*section)->name();
+ }
+ }
break;
}
/** target dependent sections **/
case LDFileFormat::Target: {
- if (!m_pELFReader->readTargetSection(pInput, m_Linker, **section))
+ SectionData* sd = IRBuilder::CreateSectionData(**section);
+ if (!m_Backend.readSection(pInput, *sd)) {
fatal(diag::err_cannot_read_target_section) << (*section)->name();
+ }
break;
}
/** BSS sections **/
case LDFileFormat::BSS: {
- LDSection& output_bss = m_Linker.getOrCreateOutputSectHdr(
- (*section)->name(),
- LDFileFormat::BSS,
- llvm::ELF::SHT_NOBITS,
- llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE);
-
- SectionData& sect_data = m_Linker.getOrCreateSectData(**section);
- /* value, valsize, size*/
- FillFragment* frag = new FillFragment(0x0, 1, (*section)->size());
-
- uint64_t size = m_Linker.getLayout().appendFragment(*frag,
- sect_data,
- (*section)->align());
- output_bss.setSize(output_bss.size() + size);
+ IRBuilder::CreateBSS(**section);
break;
}
// ignore
case LDFileFormat::Null:
case LDFileFormat::NamePool:
+ case LDFileFormat::Ignore:
+ case LDFileFormat::StackNote:
continue;
// warning
case LDFileFormat::EhFrameHdr:
@@ -205,7 +231,7 @@
return true;
}
-/// readSymbols - read symbols into MCLinker from the input relocatable object.
+/// readSymbols - read symbols into FragmentLinker from the input relocatable object.
bool ELFObjectReader::readSymbols(Input& pInput)
{
assert(pInput.hasMemArea());
@@ -245,32 +271,39 @@
assert(pInput.hasMemArea());
MemoryArea* mem = pInput.memArea();
- LDContext::sect_iterator section, sectEnd = pInput.context()->sectEnd();
- for (section = pInput.context()->sectBegin(); section != sectEnd; ++section) {
- // ignore the section if the LDSection* in input context is NULL
- if (NULL == *section)
- continue;
+ LDContext::sect_iterator rs, rsEnd = pInput.context()->relocSectEnd();
+ for (rs = pInput.context()->relocSectBegin(); rs != rsEnd; ++rs) {
+ if (LDFileFormat::Ignore == (*rs)->kind())
+ continue;
- if ((*section)->type() == llvm::ELF::SHT_RELA &&
- (*section)->kind() == LDFileFormat::Relocation) {
- MemoryRegion* region = mem->request(
- pInput.fileOffset() + (*section)->offset(), (*section)->size());
- bool result = m_pELFReader->readRela(pInput, m_Linker, **section,
- *region);
- mem->release(region);
- if (!result)
+ uint32_t offset = pInput.fileOffset() + (*rs)->offset();
+ uint32_t size = (*rs)->size();
+ MemoryRegion* region = mem->request(offset, size);
+ IRBuilder::CreateRelocData(**rs); ///< create relocation data for the header
+ switch ((*rs)->type()) {
+ case llvm::ELF::SHT_RELA: {
+ if (!m_pELFReader->readRela(pInput, m_Linker, **rs, *region)) {
+ mem->release(region);
+ return false;
+ }
+ break;
+ }
+ case llvm::ELF::SHT_REL: {
+ if (!m_pELFReader->readRel(pInput, m_Linker, **rs, *region)) {
+ mem->release(region);
+ return false;
+ }
+ break;
+ }
+ default: { ///< should not enter
+ mem->release(region);
return false;
- }
- else if ((*section)->type() == llvm::ELF::SHT_REL &&
- (*section)->kind() == LDFileFormat::Relocation) {
- MemoryRegion* region = mem->request(
- pInput.fileOffset() + (*section)->offset(), (*section)->size());
- bool result = m_pELFReader->readRel(pInput, m_Linker, **section, *region);
- mem->release(region);
- if (!result)
- return false;
- }
- }
+ }
+ } // end of switch
+
+ mem->release(region);
+ } // end of for all relocation data
+
return true;
}
diff --git a/lib/LD/ELFObjectWriter.cpp b/lib/LD/ELFObjectWriter.cpp
index 2795d3f..ee9a7ac 100644
--- a/lib/LD/ELFObjectWriter.cpp
+++ b/lib/LD/ELFObjectWriter.cpp
@@ -6,13 +6,22 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "mcld/LD/ELFObjectWriter.h"
+#include <mcld/LD/ELFObjectWriter.h>
+#include <mcld/Module.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Support/MemoryArea.h>
+
+#include <llvm/Support/system_error.h>
+using namespace llvm;
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// ELFObjectWriter
-ELFObjectWriter::ELFObjectWriter(GNULDBackend& pBackend, MCLinker& pLinker)
+//===----------------------------------------------------------------------===//
+ELFObjectWriter::ELFObjectWriter(GNULDBackend& pBackend,
+ FragmentLinker& pLinker)
: ObjectWriter(pBackend), ELFWriter(pBackend), m_Linker(pLinker) {
}
@@ -20,4 +29,100 @@
{
}
+llvm::error_code ELFObjectWriter::writeObject(Module& pModule,
+ MemoryArea& pOutput)
+{
+ // Write out name pool sections: .symtab, .strtab
+ target().emitRegNamePools(pModule, pOutput);
+
+ // Write out regular ELF sections
+ Module::iterator sect, sectEnd = pModule.end();
+ for (sect = pModule.begin(); sect != sectEnd; ++sect) {
+ MemoryRegion* region = NULL;
+ // request output region
+ switch((*sect)->kind()) {
+ case LDFileFormat::Regular:
+ case LDFileFormat::Relocation:
+ case LDFileFormat::Target:
+ case LDFileFormat::Debug:
+ case LDFileFormat::GCCExceptTable:
+ case LDFileFormat::EhFrame: {
+ region = pOutput.request((*sect)->offset(), (*sect)->size());
+ if (NULL == region) {
+ llvm::report_fatal_error(llvm::Twine("cannot get enough memory region for output section `") +
+ llvm::Twine((*sect)->name()) +
+ llvm::Twine("'.\n"));
+ }
+ break;
+ }
+ case LDFileFormat::Null:
+ case LDFileFormat::NamePool:
+ case LDFileFormat::BSS:
+ case LDFileFormat::Note:
+ case LDFileFormat::MetaData:
+ case LDFileFormat::Version:
+ case LDFileFormat::EhFrameHdr:
+ case LDFileFormat::StackNote:
+ // ignore these sections
+ continue;
+ default: {
+ llvm::errs() << "WARNING: unsupported section kind: "
+ << (*sect)->kind()
+ << " of section "
+ << (*sect)->name()
+ << ".\n";
+ continue;
+ }
+ }
+
+ // write out sections with data
+ switch((*sect)->kind()) {
+ case LDFileFormat::Regular:
+ case LDFileFormat::Debug:
+ case LDFileFormat::GCCExceptTable:
+ case LDFileFormat::EhFrame: {
+ // FIXME: if optimization of exception handling sections is enabled,
+ // then we should emit these sections by the other way.
+ emitSectionData(**sect, *region);
+ break;
+ }
+ case LDFileFormat::Relocation:
+ emitRelocation(m_Linker.getLDInfo(), **sect, *region);
+ break;
+ case LDFileFormat::Target:
+ target().emitSectionData(**sect, *region);
+ break;
+ default:
+ continue;
+ }
+ } // end of for loop
+
+ emitELFShStrTab(target().getOutputFormat()->getShStrTab(),
+ pModule,
+ pOutput);
+
+ if (32 == target().bitclass()) {
+ // Write out ELF header
+ // Write out section header table
+ writeELF32Header(m_Linker.getLDInfo(),
+ pModule,
+ pOutput);
+
+ emitELF32SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
+ }
+ else if (64 == target().bitclass()) {
+ // Write out ELF header
+ // Write out section header table
+ writeELF64Header(m_Linker.getLDInfo(),
+ pModule,
+ pOutput);
+
+ emitELF64SectionHeader(pModule, m_Linker.getLDInfo(), pOutput);
+ }
+ else
+ return make_error_code(errc::not_supported);
+
+ pOutput.clear();
+ return llvm::make_error_code(llvm::errc::success);
+}
diff --git a/lib/LD/ELFReader.cpp b/lib/LD/ELFReader.cpp
index fce4e8b..7f105b3 100644
--- a/lib/LD/ELFReader.cpp
+++ b/lib/LD/ELFReader.cpp
@@ -6,87 +6,31 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+#include <mcld/LD/ELFReader.h>
+
+#include <mcld/IRBuilder.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Object/ObjectBuilder.h>
+
+#include <cstring>
#include <llvm/ADT/StringRef.h>
#include <llvm/ADT/Twine.h>
#include <llvm/Support/ELF.h>
#include <llvm/Support/Host.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/LD/ELFReader.h>
-#include <mcld/Target/GNULDBackend.h>
-#include <mcld/Support/MemoryArea.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/MsgHandling.h>
-#include <cstring>
-
using namespace mcld;
//===----------------------------------------------------------------------===//
// ELFReaderIF
-/// getLDSectionKind
-LDFileFormat::Kind
-ELFReaderIF::getLDSectionKind(uint32_t pType, const char* pName) const
-{
- // name rules
- llvm::StringRef name(pName);
- if (name.startswith(".debug") ||
- name.startswith(".zdebug") ||
- name.startswith(".gnu.linkonce.wi.") ||
- name.startswith(".line") ||
- name.startswith(".stab"))
- return LDFileFormat::Debug;
- if (name.startswith(".comment"))
- return LDFileFormat::MetaData;
- if (name.startswith(".interp") || name.startswith(".dynamic"))
- return LDFileFormat::Note;
- if (name.startswith(".eh_frame"))
- return LDFileFormat::EhFrame;
- if (name.startswith(".eh_frame_hdr"))
- return LDFileFormat::EhFrameHdr;
- if (name.startswith(".gcc_except_table"))
- return LDFileFormat::GCCExceptTable;
-
- // type rules
- switch(pType) {
- case llvm::ELF::SHT_NULL:
- return LDFileFormat::Null;
- case llvm::ELF::SHT_INIT_ARRAY:
- case llvm::ELF::SHT_FINI_ARRAY:
- case llvm::ELF::SHT_PREINIT_ARRAY:
- case llvm::ELF::SHT_PROGBITS:
- return LDFileFormat::Regular;
- case llvm::ELF::SHT_SYMTAB:
- case llvm::ELF::SHT_DYNSYM:
- case llvm::ELF::SHT_STRTAB:
- return LDFileFormat::NamePool;
- case llvm::ELF::SHT_RELA:
- case llvm::ELF::SHT_REL:
- return LDFileFormat::Relocation;
- case llvm::ELF::SHT_NOBITS:
- return LDFileFormat::BSS;
- case llvm::ELF::SHT_DYNAMIC:
- case llvm::ELF::SHT_NOTE:
- return LDFileFormat::Note;
- case llvm::ELF::SHT_HASH:
- case llvm::ELF::SHT_SHLIB:
- return LDFileFormat::MetaData;
- case llvm::ELF::SHT_GROUP:
- return LDFileFormat::Group;
- case llvm::ELF::SHT_GNU_versym:
- case llvm::ELF::SHT_GNU_verdef:
- case llvm::ELF::SHT_GNU_verneed:
- return LDFileFormat::Version;
- default:
- if ((pType >= llvm::ELF::SHT_LOPROC && pType <= llvm::ELF::SHT_HIPROC) ||
- (pType >= llvm::ELF::SHT_LOOS && pType <= llvm::ELF::SHT_HIOS) ||
- (pType >= llvm::ELF::SHT_LOUSER && pType <= llvm::ELF::SHT_HIUSER))
- return LDFileFormat::Target;
- fatal(diag::err_unsupported_section) << pName << pType;
- }
- return LDFileFormat::MetaData;
-}
-
+//===----------------------------------------------------------------------===//
/// getSymType
ResolveInfo::Type ELFReaderIF::getSymType(uint8_t pInfo, uint16_t pShndx) const
{
@@ -112,7 +56,8 @@
// an ELF symbol defined in a section which we are not including
// must be treated as an Undefined.
// @ref Google gold linker: symtab.cc: 1086
- if (NULL == pInput.context()->getSection(pShndx))
+ if (NULL == pInput.context()->getSection(pShndx) ||
+ LDFileFormat::Ignore == pInput.context()->getSection(pShndx)->kind())
return ResolveInfo::Undefined;
return ResolveInfo::Define;
}
@@ -153,13 +98,15 @@
/// getSymFragmentRef
FragmentRef*
ELFReaderIF::getSymFragmentRef(Input& pInput,
- MCLinker& pLinker,
uint16_t pShndx,
uint32_t pOffset) const
{
+ if (Input::DynObj == pInput.type())
+ return FragmentRef::Null();
+
if (pShndx == llvm::ELF::SHN_UNDEF || pShndx >= llvm::ELF::SHN_LORESERVE)
- return NULL;
+ return FragmentRef::Null();
LDSection* sect_hdr = pInput.context()->getSection(pShndx);
@@ -167,8 +114,13 @@
unreachable(diag::unreachable_invalid_section_idx) << pShndx
<< pInput.path().native();
- FragmentRef* result = pLinker.getLayout().getFragmentRef(*sect_hdr, pOffset);
- return result;
+ if (LDFileFormat::Ignore == sect_hdr->kind())
+ return FragmentRef::Null();
+
+ if (LDFileFormat::Group == sect_hdr->kind())
+ return FragmentRef::Null();
+
+ return FragmentRef::Create(*sect_hdr, pOffset);
}
/// getSymVisibility
@@ -204,17 +156,510 @@
return 0x0;
}
-bool ELFReaderIF::readEhFrame(Input& pInput,
- MCLinker& pLinker,
- LDSection& pInputSectHdr) const
+//===----------------------------------------------------------------------===//
+// ELFReader<32, true>
+//===----------------------------------------------------------------------===//
+/// constructor
+ELFReader<32, true>::ELFReader(GNULDBackend& pBackend)
+ : ELFReaderIF(pBackend) {
+}
+
+/// destructor
+ELFReader<32, true>::~ELFReader()
{
- LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(),
- pInputSectHdr.kind(),
- pInputSectHdr.type(),
- pInputSectHdr.flag());
+}
- size_t size = pLinker.addEhFrame(pInput, pInputSectHdr, *pInput.memArea());
+/// isELF - is this a ELF file
+bool ELFReader<32, true>::isELF(void* pELFHeader) const
+{
+ llvm::ELF::Elf32_Ehdr* hdr =
+ reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+ if (0 == memcmp(llvm::ELF::ElfMagic, hdr, 4))
+ return true;
+ return false;
+}
- out_sect.setSize(out_sect.size() + size);
+/// readRegularSection - read a regular section and create fragments.
+bool
+ELFReader<32, true>::readRegularSection(Input& pInput, SectionData& pSD) const
+{
+ uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
+ uint32_t size = pSD.getSection().size();
+
+ Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
+ ObjectBuilder::AppendFragment(*frag, pSD);
return true;
}
+
+/// readSymbols - read ELF symbols and create LDSymbol
+bool ELFReader<32, true>::readSymbols(Input& pInput,
+ FragmentLinker& pLinker,
+ const MemoryRegion& pRegion,
+ const char* pStrTab) const
+{
+ // get number of symbols
+ size_t entsize = pRegion.size()/sizeof(llvm::ELF::Elf32_Sym);
+ const llvm::ELF::Elf32_Sym* symtab =
+ reinterpret_cast<const llvm::ELF::Elf32_Sym*>(pRegion.start());
+
+ uint32_t st_name = 0x0;
+ uint32_t st_value = 0x0;
+ uint32_t st_size = 0x0;
+ uint8_t st_info = 0x0;
+ uint8_t st_other = 0x0;
+ uint16_t st_shndx = 0x0;
+
+ // skip the first NULL symbol
+ pInput.context()->addSymbol(LDSymbol::Null());
+
+ for (size_t idx = 1; idx < entsize; ++idx) {
+ st_info = symtab[idx].st_info;
+ st_other = symtab[idx].st_other;
+
+ if (llvm::sys::isLittleEndianHost()) {
+ st_name = symtab[idx].st_name;
+ st_value = symtab[idx].st_value;
+ st_size = symtab[idx].st_size;
+ st_shndx = symtab[idx].st_shndx;
+ }
+ else {
+ st_name = bswap32(symtab[idx].st_name);
+ st_value = bswap32(symtab[idx].st_value);
+ st_size = bswap32(symtab[idx].st_size);
+ st_shndx = bswap16(symtab[idx].st_shndx);
+ }
+
+ // If the section should not be included, set the st_shndx SHN_UNDEF
+ // - A section in interrelated groups are not included.
+ if (pInput.type() == Input::Object &&
+ st_shndx < llvm::ELF::SHN_LORESERVE &&
+ st_shndx != llvm::ELF::SHN_UNDEF) {
+ if (NULL == pInput.context()->getSection(st_shndx))
+ st_shndx = llvm::ELF::SHN_UNDEF;
+ }
+
+ // get ld_type
+ ResolveInfo::Type ld_type = getSymType(st_info, st_shndx);
+
+ // get ld_desc
+ ResolveInfo::Desc ld_desc = getSymDesc(st_shndx, pInput);
+
+ // get ld_binding
+ ResolveInfo::Binding ld_binding = getSymBinding((st_info >> 4), st_shndx, st_other);
+
+ // get ld_value - ld_value must be section relative.
+ uint64_t ld_value = getSymValue(st_value, st_shndx, pInput);
+
+ // get the input fragment
+ FragmentRef* ld_frag_ref = getSymFragmentRef(pInput,
+ st_shndx,
+ ld_value);
+
+ // get ld_vis
+ ResolveInfo::Visibility ld_vis = getSymVisibility(st_other);
+
+ // get ld_name
+ llvm::StringRef ld_name;
+ if (ResolveInfo::Section == ld_type) {
+ // Section symbol's st_name is the section index.
+ LDSection* section = pInput.context()->getSection(st_shndx);
+ assert(NULL != section && "get a invalid section");
+ ld_name = llvm::StringRef(section->name());
+ }
+ else {
+ ld_name = llvm::StringRef(pStrTab + st_name);
+ }
+
+
+ // push into FragmentLinker
+ LDSymbol* input_sym = NULL;
+
+ if (pInput.type() == Input::Object) {
+ input_sym = pLinker.addSymbol<Input::Object>(ld_name,
+ ld_type,
+ ld_desc,
+ ld_binding,
+ st_size,
+ ld_value,
+ ld_frag_ref,
+ ld_vis);
+ // push into the input file
+ pInput.context()->addSymbol(input_sym);
+ continue;
+ }
+ else if (pInput.type() == Input::DynObj) {
+ input_sym = pLinker.addSymbol<Input::DynObj>(ld_name,
+ ld_type,
+ ld_desc,
+ ld_binding,
+ st_size,
+ ld_value,
+ ld_frag_ref,
+ ld_vis);
+ continue;
+ }
+
+ } // end of for loop
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// ELFReader::read relocations - read ELF rela and rel, and create Relocation
+//===----------------------------------------------------------------------===//
+/// ELFReader::readRela - read ELF rela and create Relocation
+bool ELFReader<32, true>::readRela(Input& pInput,
+ FragmentLinker& pLinker,
+ LDSection& pSection,
+ const MemoryRegion& pRegion) const
+{
+ // get the number of rela
+ size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rela);
+ const llvm::ELF::Elf32_Rela* relaTab =
+ reinterpret_cast<const llvm::ELF::Elf32_Rela*>(pRegion.start());
+
+ for (size_t idx=0; idx < entsize; ++idx) {
+ uint32_t r_offset = 0x0;
+ uint32_t r_info = 0x0;
+ int32_t r_addend = 0;
+ if (llvm::sys::isLittleEndianHost()) {
+ r_offset = relaTab[idx].r_offset;
+ r_info = relaTab[idx].r_info;
+ r_addend = relaTab[idx].r_addend;
+ }
+ else {
+ r_offset = bswap32(relaTab[idx].r_offset);
+ r_info = bswap32(relaTab[idx].r_info);
+ r_addend = bswap32(relaTab[idx].r_addend);
+ }
+
+ uint8_t r_type = static_cast<unsigned char>(r_info);
+ uint32_t r_sym = (r_info >> 8);
+ LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
+ if (NULL == symbol) {
+ fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
+ }
+
+ pLinker.addRelocation(r_type, *symbol, pSection, r_offset, r_addend);
+ } // end of for
+ return true;
+}
+
+/// readRel - read ELF rel and create Relocation
+bool ELFReader<32, true>::readRel(Input& pInput,
+ FragmentLinker& pLinker,
+ LDSection& pSection,
+ const MemoryRegion& pRegion) const
+{
+ // get the number of rel
+ size_t entsize = pRegion.size() / sizeof(llvm::ELF::Elf32_Rel);
+ const llvm::ELF::Elf32_Rel* relTab =
+ reinterpret_cast<const llvm::ELF::Elf32_Rel*>(pRegion.start());
+
+ for (size_t idx=0; idx < entsize; ++idx) {
+ uint32_t r_offset = 0x0;
+ uint32_t r_info = 0x0;
+ if (llvm::sys::isLittleEndianHost()) {
+ r_offset = relTab[idx].r_offset;
+ r_info = relTab[idx].r_info;
+ }
+ else {
+ r_offset = bswap32(relTab[idx].r_offset);
+ r_info = bswap32(relTab[idx].r_info);
+ }
+
+ uint8_t r_type = static_cast<unsigned char>(r_info);
+ uint32_t r_sym = (r_info >> 8);
+
+ LDSymbol* symbol = pInput.context()->getSymbol(r_sym);
+ if (NULL == symbol) {
+ fatal(diag::err_cannot_read_symbol) << r_sym << pInput.path();
+ }
+
+ pLinker.addRelocation(r_type, *symbol, pSection, r_offset);
+ } // end of for
+ return true;
+}
+
+/// isMyEndian - is this ELF file in the same endian to me?
+bool ELFReader<32, true>::isMyEndian(void* pELFHeader) const
+{
+ llvm::ELF::Elf32_Ehdr* hdr =
+ reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+
+ return (hdr->e_ident[llvm::ELF::EI_DATA] == llvm::ELF::ELFDATA2LSB);
+}
+
+/// isMyMachine - is this ELF file generated for the same machine.
+bool ELFReader<32, true>::isMyMachine(void* pELFHeader) const
+{
+ llvm::ELF::Elf32_Ehdr* hdr =
+ reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+
+ if (llvm::sys::isLittleEndianHost())
+ return (hdr->e_machine == target().machine());
+ return (bswap16(hdr->e_machine) == target().machine());
+}
+
+/// fileType - return the file type
+Input::Type ELFReader<32, true>::fileType(void* pELFHeader) const
+{
+ llvm::ELF::Elf32_Ehdr* hdr =
+ reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+ uint32_t type = 0x0;
+ if (llvm::sys::isLittleEndianHost())
+ type = hdr->e_type;
+ else
+ type = bswap16(hdr->e_type);
+
+ switch(type) {
+ case llvm::ELF::ET_REL:
+ return Input::Object;
+ case llvm::ELF::ET_EXEC:
+ return Input::Exec;
+ case llvm::ELF::ET_DYN:
+ return Input::DynObj;
+ case llvm::ELF::ET_CORE:
+ return Input::CoreFile;
+ case llvm::ELF::ET_NONE:
+ default:
+ return Input::Unknown;
+ }
+}
+
+/// readSectionHeaders - read ELF section header table and create LDSections
+bool
+ELFReader<32, true>::readSectionHeaders(Input& pInput, void* pELFHeader) const
+{
+ llvm::ELF::Elf32_Ehdr* ehdr =
+ reinterpret_cast<llvm::ELF::Elf32_Ehdr*>(pELFHeader);
+
+ uint32_t shoff = 0x0;
+ uint16_t shentsize = 0x0;
+ uint16_t shnum = 0x0;
+ uint16_t shstrtab = 0x0;
+
+ if (llvm::sys::isLittleEndianHost()) {
+ shoff = ehdr->e_shoff;
+ shentsize = ehdr->e_shentsize;
+ shnum = ehdr->e_shnum;
+ shstrtab = ehdr->e_shstrndx;
+ }
+ else {
+ shoff = bswap32(ehdr->e_shoff);
+ shentsize = bswap16(ehdr->e_shentsize);
+ shnum = bswap16(ehdr->e_shnum);
+ shstrtab = bswap16(ehdr->e_shstrndx);
+ }
+
+ // If the file has no section header table, e_shoff holds zero.
+ if (0x0 == shoff)
+ return true;
+
+ MemoryRegion* shdr_region = pInput.memArea()->request(
+ pInput.fileOffset() + shoff, shnum*shentsize);
+ llvm::ELF::Elf32_Shdr* shdrTab =
+ reinterpret_cast<llvm::ELF::Elf32_Shdr*>(shdr_region->start());
+
+ uint32_t sh_name = 0x0;
+ uint32_t sh_type = 0x0;
+ uint32_t sh_flags = 0x0;
+ uint32_t sh_offset = 0x0;
+ uint32_t sh_size = 0x0;
+ uint32_t sh_link = 0x0;
+ uint32_t sh_info = 0x0;
+ uint32_t sh_addralign = 0x0;
+
+ // get .shstrtab first
+ llvm::ELF::Elf32_Shdr* shdr = &shdrTab[shstrtab];
+ if (llvm::sys::isLittleEndianHost()) {
+ sh_offset = shdr->sh_offset;
+ sh_size = shdr->sh_size;
+ }
+ else {
+ sh_offset = bswap32(shdr->sh_offset);
+ sh_size = bswap32(shdr->sh_size);
+ }
+
+ MemoryRegion* sect_name_region = pInput.memArea()->request(
+ pInput.fileOffset() + sh_offset, sh_size);
+ const char* sect_name =
+ reinterpret_cast<const char*>(sect_name_region->start());
+
+ LinkInfoList link_info_list;
+
+ // create all LDSections, including first NULL section.
+ for (size_t idx = 0; idx < shnum; ++idx) {
+ if (llvm::sys::isLittleEndianHost()) {
+ sh_name = shdrTab[idx].sh_name;
+ sh_type = shdrTab[idx].sh_type;
+ sh_flags = shdrTab[idx].sh_flags;
+ sh_offset = shdrTab[idx].sh_offset;
+ sh_size = shdrTab[idx].sh_size;
+ sh_link = shdrTab[idx].sh_link;
+ sh_info = shdrTab[idx].sh_info;
+ sh_addralign = shdrTab[idx].sh_addralign;
+ }
+ else {
+ sh_name = bswap32(shdrTab[idx].sh_name);
+ sh_type = bswap32(shdrTab[idx].sh_type);
+ sh_flags = bswap32(shdrTab[idx].sh_flags);
+ sh_offset = bswap32(shdrTab[idx].sh_offset);
+ sh_size = bswap32(shdrTab[idx].sh_size);
+ sh_link = bswap32(shdrTab[idx].sh_link);
+ sh_info = bswap32(shdrTab[idx].sh_info);
+ sh_addralign = bswap32(shdrTab[idx].sh_addralign);
+ }
+
+ LDSection* section = IRBuilder::CreateELFHeader(pInput,
+ sect_name+sh_name,
+ sh_type,
+ sh_flags,
+ sh_addralign);
+ section->setSize(sh_size);
+ section->setOffset(sh_offset);
+ section->setInfo(sh_info);
+
+ if (sh_link != 0x0 || sh_info != 0x0) {
+ LinkInfo link_info = { section, sh_link, sh_info };
+ link_info_list.push_back(link_info);
+ }
+ } // end of for
+
+ // set up InfoLink
+ LinkInfoList::iterator info, infoEnd = link_info_list.end();
+ for (info = link_info_list.begin(); info != infoEnd; ++info) {
+ if (LDFileFormat::NamePool == info->section->kind() ||
+ LDFileFormat::Group == info->section->kind() ||
+ LDFileFormat::Note == info->section->kind()) {
+ info->section->setLink(pInput.context()->getSection(info->sh_link));
+ continue;
+ }
+ if (LDFileFormat::Relocation == info->section->kind()) {
+ info->section->setLink(pInput.context()->getSection(info->sh_info));
+ continue;
+ }
+ }
+
+ pInput.memArea()->release(shdr_region);
+ pInput.memArea()->release(sect_name_region);
+
+ return true;
+}
+
+/// readSignature - read a symbol from the given Input and index in symtab
+/// This is used to get the signature of a group section.
+ResolveInfo* ELFReader<32, true>::readSignature(Input& pInput,
+ LDSection& pSymTab,
+ uint32_t pSymIdx) const
+{
+ LDSection* symtab = &pSymTab;
+ LDSection* strtab = symtab->getLink();
+ assert(NULL != symtab && NULL != strtab);
+
+ uint32_t offset = pInput.fileOffset() + symtab->offset() +
+ sizeof(llvm::ELF::Elf32_Sym) * pSymIdx;
+ MemoryRegion* symbol_region =
+ pInput.memArea()->request(offset, sizeof(llvm::ELF::Elf32_Sym));
+ llvm::ELF::Elf32_Sym* entry =
+ reinterpret_cast<llvm::ELF::Elf32_Sym*>(symbol_region->start());
+
+ uint32_t st_name = 0x0;
+ uint8_t st_info = 0x0;
+ uint8_t st_other = 0x0;
+ uint16_t st_shndx = 0x0;
+ st_info = entry->st_info;
+ st_other = entry->st_other;
+ if (llvm::sys::isLittleEndianHost()) {
+ st_name = entry->st_name;
+ st_shndx = entry->st_shndx;
+ }
+ else {
+ st_name = bswap32(entry->st_name);
+ st_shndx = bswap16(entry->st_shndx);
+ }
+
+ MemoryRegion* strtab_region = pInput.memArea()->request(
+ pInput.fileOffset() + strtab->offset(), strtab->size());
+
+ // get ld_name
+ llvm::StringRef ld_name(
+ reinterpret_cast<char*>(strtab_region->start() + st_name));
+
+ ResolveInfo* result = ResolveInfo::Create(ld_name);
+ result->setSource(pInput.type() == Input::DynObj);
+ result->setType(static_cast<ResolveInfo::Type>(st_info & 0xF));
+ result->setDesc(getSymDesc(st_shndx, pInput));
+ result->setBinding(getSymBinding((st_info >> 4), st_shndx, st_other));
+ result->setVisibility(getSymVisibility(st_other));
+
+ // release regions
+ pInput.memArea()->release(symbol_region);
+ pInput.memArea()->release(strtab_region);
+
+ return result;
+}
+
+/// readDynamic - read ELF .dynamic in input dynobj
+bool ELFReader<32, true>::readDynamic(Input& pInput) const
+{
+ assert(pInput.type() == Input::DynObj);
+ const LDSection* dynamic_sect = pInput.context()->getSection(".dynamic");
+ if (NULL == dynamic_sect) {
+ fatal(diag::err_cannot_read_section) << ".dynamic";
+ }
+ const LDSection* dynstr_sect = dynamic_sect->getLink();
+ if (NULL == dynstr_sect) {
+ fatal(diag::err_cannot_read_section) << ".dynstr";
+ }
+
+ MemoryRegion* dynamic_region = pInput.memArea()->request(
+ pInput.fileOffset() + dynamic_sect->offset(), dynamic_sect->size());
+
+ MemoryRegion* dynstr_region = pInput.memArea()->request(
+ pInput.fileOffset() + dynstr_sect->offset(), dynstr_sect->size());
+
+ assert(NULL != dynamic_region && NULL != dynstr_region);
+
+ const llvm::ELF::Elf32_Dyn* dynamic =
+ (llvm::ELF::Elf32_Dyn*) dynamic_region->start();
+ const char* dynstr = (const char*) dynstr_region->start();
+ bool hasSOName = false;
+ size_t numOfEntries = dynamic_sect->size() / sizeof(llvm::ELF::Elf32_Dyn);
+
+ for (size_t idx = 0; idx < numOfEntries; ++idx) {
+
+ llvm::ELF::Elf32_Sword d_tag = 0x0;
+ llvm::ELF::Elf32_Word d_val = 0x0;
+
+ if (llvm::sys::isLittleEndianHost()) {
+ d_tag = dynamic[idx].d_tag;
+ d_val = dynamic[idx].d_un.d_val;
+ } else {
+ d_tag = bswap32(dynamic[idx].d_tag);
+ d_val = bswap32(dynamic[idx].d_un.d_val);
+ }
+
+ switch (d_tag) {
+ case llvm::ELF::DT_SONAME:
+ assert(d_val < dynstr_sect->size());
+ pInput.setName(sys::fs::Path(dynstr + d_val).filename().native());
+ hasSOName = true;
+ break;
+ case llvm::ELF::DT_NEEDED:
+ // TODO:
+ break;
+ case llvm::ELF::DT_NULL:
+ default:
+ break;
+ }
+ }
+
+ // if there is no SONAME in .dynamic, then set it from input path
+ if (!hasSOName)
+ pInput.setName(pInput.path().filename().native());
+
+ pInput.memArea()->release(dynamic_region);
+ pInput.memArea()->release(dynstr_region);
+ return true;
+}
+
diff --git a/lib/LD/ELFSegment.cpp b/lib/LD/ELFSegment.cpp
index dbefbc5..ae328ca 100644
--- a/lib/LD/ELFSegment.cpp
+++ b/lib/LD/ELFSegment.cpp
@@ -35,3 +35,33 @@
ELFSegment::~ELFSegment()
{
}
+
+bool ELFSegment::isDataSegment() const
+{
+ bool result = false;
+ if ((type() == llvm::ELF::PT_LOAD) && (flag() & llvm::ELF::PF_W) != 0x0) {
+ for (const_sect_iterator it = begin(), ie = end(); it != ie; ++it) {
+ if ((*it)->kind() != LDFileFormat::BSS) {
+ result = true;
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+bool ELFSegment::isBssSegment() const
+{
+ bool result = false;
+ if ((type() == llvm::ELF::PT_LOAD) && (flag() & llvm::ELF::PF_W) != 0x0) {
+ const_sect_iterator it = begin(), ie = end();
+ for (; it != ie; ++it) {
+ if ((*it)->kind() != LDFileFormat::BSS)
+ break;
+ }
+ if (it == ie)
+ result = true;
+ }
+ return result;
+}
+
diff --git a/lib/LD/ELFWriter.cpp b/lib/LD/ELFWriter.cpp
index bf3152a..93fc4b9 100644
--- a/lib/LD/ELFWriter.cpp
+++ b/lib/LD/ELFWriter.cpp
@@ -13,146 +13,152 @@
#include <llvm/Support/ELF.h>
#include <llvm/Support/Casting.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/Module.h>
#include <mcld/ADT/SizeTraits.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/LD/AlignFragment.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/RegionFragment.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Fragment/AlignFragment.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Fragment/Stub.h>
+#include <mcld/Fragment/NullFragment.h>
#include <mcld/LD/ELFWriter.h>
#include <mcld/LD/LDSymbol.h>
#include <mcld/LD/LDSection.h>
-#include <mcld/LD/Layout.h>
+#include <mcld/LD/SectionData.h>
#include <mcld/LD/ELFSegment.h>
#include <mcld/LD/ELFSegmentFactory.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/LD/EhFrame.h>
#include <mcld/Target/GNULDBackend.h>
+#include <mcld/Support/MemoryArea.h>
#include <mcld/Support/MemoryRegion.h>
using namespace llvm::ELF;
using namespace mcld;
/// writeELF32Header - write ELF header
-void ELFWriter::writeELF32Header(const MCLDInfo& pLDInfo,
- const Layout& pLayout,
- const GNULDBackend& pBackend,
- Output& pOutput) const
+void ELFWriter::writeELF32Header(const LinkerConfig& pConfig,
+ const Module& pModule,
+ MemoryArea& pOutput) const
{
- assert(pOutput.hasMemArea());
+ // ELF header must start from 0x0
+ MemoryRegion *region = pOutput.request(0, sizeof(Elf32_Ehdr));
+ Elf32_Ehdr* header = (Elf32_Ehdr*)region->start();
- // ELF header must start from 0x0
- MemoryRegion *region = pOutput.memArea()->request(0,
- sizeof(Elf32_Ehdr));
- Elf32_Ehdr* header = (Elf32_Ehdr*)region->start();
+ memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
- memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
-
- header->e_ident[EI_CLASS] = ELFCLASS32;
- header->e_ident[EI_DATA] = pBackend.isLittleEndian()?
+ header->e_ident[EI_CLASS] = ELFCLASS32;
+ header->e_ident[EI_DATA] = target().isLittleEndian()?
ELFDATA2LSB : ELFDATA2MSB;
- header->e_ident[EI_VERSION] = pBackend.ELFVersion();
- header->e_ident[EI_OSABI] = pBackend.OSABI();
- header->e_ident[EI_ABIVERSION] = pBackend.ABIVersion();
+ header->e_ident[EI_VERSION] = target().ELFVersion();
+ header->e_ident[EI_OSABI] = target().OSABI();
+ header->e_ident[EI_ABIVERSION] = target().ABIVersion();
- // FIXME: add processor-specific and core file types.
- switch(pOutput.type()) {
- case Output::Object:
+ // FIXME: add processor-specific and core file types.
+ switch(pConfig.codeGenType()) {
+ case LinkerConfig::Object:
header->e_type = ET_REL;
break;
- case Output::DynObj:
+ case LinkerConfig::DynObj:
header->e_type = ET_DYN;
break;
- case Output::Exec:
+ case LinkerConfig::Exec:
header->e_type = ET_EXEC;
break;
default:
- llvm::errs() << "unspported output file type: " << pOutput.type() << ".\n";
+ llvm::errs() << "unspported output file type: " << pConfig.codeGenType() << ".\n";
header->e_type = ET_NONE;
- }
- header->e_machine = pBackend.machine();
- header->e_version = header->e_ident[EI_VERSION];
- header->e_entry = getEntryPoint(pLDInfo, pLayout, pBackend, pOutput);
- header->e_phoff = sizeof(Elf32_Ehdr);
- header->e_shoff = getELF32LastStartOffset(pOutput);
- header->e_flags = pBackend.flags();
- header->e_ehsize = sizeof(Elf32_Ehdr);
- header->e_phentsize = sizeof(Elf32_Phdr);
- header->e_phnum = pBackend.numOfSegments();
- header->e_shentsize = sizeof(Elf32_Shdr);
- header->e_shnum = pOutput.context()->numOfSections();
- header->e_shstrndx = pOutput.context()->getSectionIdx(".shstrtab");
+ }
+ header->e_machine = target().machine();
+ header->e_version = header->e_ident[EI_VERSION];
+ header->e_entry = getEntryPoint(pConfig, pModule);
+
+ if (LinkerConfig::Object != pConfig.codeGenType())
+ header->e_phoff = sizeof(Elf32_Ehdr);
+ else
+ header->e_phoff = 0x0;
+
+ header->e_shoff = getELF32LastStartOffset(pModule);
+ header->e_flags = target().flags();
+ header->e_ehsize = sizeof(Elf32_Ehdr);
+ header->e_phentsize = sizeof(Elf32_Phdr);
+ header->e_phnum = target().numOfSegments();
+ header->e_shentsize = sizeof(Elf32_Shdr);
+ header->e_shnum = pModule.size();
+ header->e_shstrndx = pModule.getSection(".shstrtab")->index();
}
/// writeELF64Header - write ELF header
-void ELFWriter::writeELF64Header(const MCLDInfo& pLDInfo,
- const Layout& pLayout,
- const GNULDBackend& pBackend,
- Output& pOutput) const
+void ELFWriter::writeELF64Header(const LinkerConfig& pConfig,
+ const Module& pModule,
+ MemoryArea& pOutput) const
{
- assert(pOutput.hasMemArea());
+ // ELF header must start from 0x0
+ MemoryRegion *region = pOutput.request(0, sizeof(Elf64_Ehdr));
+ Elf64_Ehdr* header = (Elf64_Ehdr*)region->start();
- // ELF header must start from 0x0
- MemoryRegion *region = pOutput.memArea()->request(0,
- sizeof(Elf64_Ehdr));
- Elf64_Ehdr* header = (Elf64_Ehdr*)region->start();
+ memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
- memcpy(header->e_ident, ElfMagic, EI_MAG3+1);
-
- header->e_ident[EI_CLASS] = ELFCLASS64;
- header->e_ident[EI_DATA] = pBackend.isLittleEndian()?
+ header->e_ident[EI_CLASS] = ELFCLASS64;
+ header->e_ident[EI_DATA] = target().isLittleEndian()?
ELFDATA2LSB : ELFDATA2MSB;
- header->e_ident[EI_VERSION] = pBackend.ELFVersion();
- header->e_ident[EI_OSABI] = pBackend.OSABI();
- header->e_ident[EI_ABIVERSION] = pBackend.ABIVersion();
+ header->e_ident[EI_VERSION] = target().ELFVersion();
+ header->e_ident[EI_OSABI] = target().OSABI();
+ header->e_ident[EI_ABIVERSION] = target().ABIVersion();
- // FIXME: add processor-specific and core file types.
- switch(pOutput.type()) {
- case Output::Object:
+ // FIXME: add processor-specific and core file types.
+ switch(pConfig.codeGenType()) {
+ case LinkerConfig::Object:
header->e_type = ET_REL;
break;
- case Output::DynObj:
+ case LinkerConfig::DynObj:
header->e_type = ET_DYN;
break;
- case Output::Exec:
+ case LinkerConfig::Exec:
header->e_type = ET_EXEC;
break;
default:
- llvm::errs() << "unspported output file type: " << pOutput.type() << ".\n";
+ llvm::errs() << "unspported output file type: " << pConfig.codeGenType() << ".\n";
header->e_type = ET_NONE;
- }
- header->e_machine = pBackend.machine();
- header->e_version = header->e_ident[EI_VERSION];
- header->e_entry = getEntryPoint(pLDInfo, pLayout, pBackend, pOutput);
- header->e_phoff = sizeof(Elf64_Ehdr);
- header->e_shoff = getELF64LastStartOffset(pOutput);
- header->e_flags = pBackend.flags();
- header->e_ehsize = sizeof(Elf64_Ehdr);
- header->e_phentsize = sizeof(Elf64_Phdr);
- header->e_phnum = pBackend.numOfSegments();
- header->e_shentsize = sizeof(Elf64_Shdr);
- header->e_shnum = pOutput.context()->numOfSections();
- header->e_shstrndx = pOutput.context()->getSectionIdx(".shstrtab");
+ }
+ header->e_machine = target().machine();
+ header->e_version = header->e_ident[EI_VERSION];
+ header->e_entry = getEntryPoint(pConfig, pModule);
+
+ if (LinkerConfig::Object != pConfig.codeGenType())
+ header->e_phoff = sizeof(Elf64_Ehdr);
+ else
+ header->e_phoff = 0x0;
+
+ header->e_shoff = getELF64LastStartOffset(pModule);
+ header->e_flags = target().flags();
+ header->e_ehsize = sizeof(Elf64_Ehdr);
+ header->e_phentsize = sizeof(Elf64_Phdr);
+ header->e_phnum = target().numOfSegments();
+ header->e_shentsize = sizeof(Elf64_Shdr);
+ header->e_shnum = pModule.size();
+ header->e_shstrndx = pModule.getSection(".shstrtab")->index();
}
/// getEntryPoint
-uint64_t ELFWriter::getEntryPoint(const MCLDInfo& pLDInfo,
- const Layout& pLayout,
- const GNULDBackend& pBackend,
- const Output& pOutput) const
+uint64_t ELFWriter::getEntryPoint(const LinkerConfig& pConfig,
+ const Module& pModule) const
{
llvm::StringRef entry_name;
- if (pLDInfo.options().hasEntry())
- entry_name = pLDInfo.options().entry();
+ if (pConfig.options().hasEntry())
+ entry_name = pConfig.options().entry();
else
- entry_name = pBackend.entry();
-
+ entry_name = target().entry();
+
uint64_t result = 0x0;
- bool issue_warning = (pLDInfo.options().hasEntry()
- && (pOutput.type() != Output::Object)
- && (pOutput.type() != Output::DynObj));
+ bool issue_warning = (pConfig.options().hasEntry() &&
+ LinkerConfig::Object != pConfig.codeGenType() &&
+ LinkerConfig::DynObj != pConfig.codeGenType());
- const LDSymbol* entry_symbol = pLDInfo.getNamePool().findSymbol(entry_name);
+ const LDSymbol* entry_symbol = pModule.getNamePool().findSymbol(entry_name);
// found the symbol
if (NULL != entry_symbol) {
@@ -183,21 +189,21 @@
/// emitELF32SectionHeader - emit Elf32_Shdr
void
-ELFWriter::emitELF32SectionHeader(Output& pOutput, MCLinker& pLinker) const
+ELFWriter::emitELF32SectionHeader(const Module& pModule,
+ const LinkerConfig& pConfig,
+ MemoryArea& pOutput) const
{
// emit section header
- unsigned int sectNum = pOutput.context()->numOfSections();
+ unsigned int sectNum = pModule.size();
unsigned int header_size = sizeof(Elf32_Shdr) * sectNum;
- MemoryRegion* region = pOutput.memArea()->request(
- getELF32LastStartOffset(pOutput),
- header_size);
+ MemoryRegion* region = pOutput.request(getELF32LastStartOffset(pModule), header_size);
Elf32_Shdr* shdr = (Elf32_Shdr*)region->start();
// Iterate the SectionTable in LDContext
unsigned int sectIdx = 0;
unsigned int shstridx = 0; // NULL section has empty name
for (; sectIdx < sectNum; ++sectIdx) {
- const LDSection *ld_sect = pOutput.context()->getSection(sectIdx);
+ const LDSection *ld_sect = pModule.getSectionTable().at(sectIdx);
shdr[sectIdx].sh_name = shstridx;
shdr[sectIdx].sh_type = ld_sect->type();
shdr[sectIdx].sh_flags = ld_sect->flag();
@@ -206,8 +212,8 @@
shdr[sectIdx].sh_size = ld_sect->size();
shdr[sectIdx].sh_addralign = ld_sect->align();
shdr[sectIdx].sh_entsize = getELF32SectEntrySize(*ld_sect);
- shdr[sectIdx].sh_link = getSectLink(*ld_sect, pOutput);
- shdr[sectIdx].sh_info = getSectInfo(*ld_sect, pOutput);
+ shdr[sectIdx].sh_link = getSectLink(*ld_sect, pConfig);
+ shdr[sectIdx].sh_info = getSectInfo(*ld_sect);
// adjust strshidx
shstridx += ld_sect->name().size() + 1;
@@ -216,34 +222,32 @@
/// emitELF64SectionHeader - emit Elf64_Shdr
void
-ELFWriter::emitELF64SectionHeader(Output& pOutput, MCLinker& pLinker) const
+ELFWriter::emitELF64SectionHeader(const Module& pModule,
+ const LinkerConfig& pConfig,
+ MemoryArea& pOutput) const
{
// emit section header
- unsigned int sectNum = pOutput.context()->numOfSections();
+ unsigned int sectNum = pModule.size();
unsigned int header_size = sizeof(Elf64_Shdr) * sectNum;
- MemoryRegion* region = pOutput.memArea()->request(
- getELF64LastStartOffset(pOutput),
- header_size);
+ MemoryRegion* region = pOutput.request(getELF64LastStartOffset(pModule),
+ header_size);
Elf64_Shdr* shdr = (Elf64_Shdr*)region->start();
// Iterate the SectionTable in LDContext
unsigned int sectIdx = 0;
unsigned int shstridx = 0; // NULL section has empty name
for (; sectIdx < sectNum; ++sectIdx) {
- const LDSection *ld_sect = pOutput.context()->getSection(sectIdx);
+ const LDSection *ld_sect = pModule.getSectionTable().at(sectIdx);
shdr[sectIdx].sh_name = shstridx;
shdr[sectIdx].sh_type = ld_sect->type();
shdr[sectIdx].sh_flags = ld_sect->flag();
shdr[sectIdx].sh_addr = ld_sect->addr();
shdr[sectIdx].sh_offset = ld_sect->offset();
shdr[sectIdx].sh_size = ld_sect->size();
- shdr[sectIdx].sh_addralign = (ld_sect->hasSectionData())?
- ld_sect->getSectionData()->getAlignment():
- 0x0;
-
+ shdr[sectIdx].sh_addralign = ld_sect->align();
shdr[sectIdx].sh_entsize = getELF64SectEntrySize(*ld_sect);
- shdr[sectIdx].sh_link = getSectLink(*ld_sect, pOutput);
- shdr[sectIdx].sh_info = getSectInfo(*ld_sect, pOutput);
+ shdr[sectIdx].sh_link = getSectLink(*ld_sect, pConfig);
+ shdr[sectIdx].sh_info = getSectInfo(*ld_sect);
// adjust strshidx
shstridx += ld_sect->name().size() + 1;
@@ -252,25 +256,22 @@
/// emitELF32ProgramHeader - emit Elf32_Phdr
-void ELFWriter::emitELF32ProgramHeader(Output& pOutput,
- const GNULDBackend& pBackend) const
+void ELFWriter::emitELF32ProgramHeader(MemoryArea& pOutput) const
{
- assert(pOutput.hasMemArea());
-
uint64_t start_offset, phdr_size;
start_offset = sizeof(Elf32_Ehdr);
phdr_size = sizeof(Elf32_Phdr);
// Program header must start directly after ELF header
- MemoryRegion *region = pOutput.memArea()->request(start_offset,
- pBackend.numOfSegments() * phdr_size);
+ MemoryRegion *region = pOutput.request(start_offset,
+ target().numOfSegments() * phdr_size);
Elf32_Phdr* phdr = (Elf32_Phdr*)region->start();
// Iterate the elf segment table in GNULDBackend
size_t index = 0;
- ELFSegmentFactory::const_iterator seg = pBackend.elfSegmentTable().begin(),
- segEnd = pBackend.elfSegmentTable().end();
+ ELFSegmentFactory::const_iterator seg = target().elfSegmentTable().begin(),
+ segEnd = target().elfSegmentTable().end();
for (; seg != segEnd; ++seg, ++index) {
phdr[index].p_type = (*seg).type();
phdr[index].p_flags = (*seg).flag();
@@ -284,24 +285,21 @@
}
/// emitELF64ProgramHeader - emit ElfR64Phdr
-void ELFWriter::emitELF64ProgramHeader(Output& pOutput,
- const GNULDBackend& pBackend) const
+void ELFWriter::emitELF64ProgramHeader(MemoryArea& pOutput) const
{
- assert(pOutput.hasMemArea());
-
uint64_t start_offset, phdr_size;
start_offset = sizeof(Elf64_Ehdr);
phdr_size = sizeof(Elf64_Phdr);
// Program header must start directly after ELF header
- MemoryRegion *region = pOutput.memArea()->request(start_offset,
- pBackend.numOfSegments() * phdr_size);
+ MemoryRegion *region = pOutput.request(start_offset,
+ target().numOfSegments() * phdr_size);
Elf64_Phdr* phdr = (Elf64_Phdr*)region->start();
// Iterate the elf segment table in GNULDBackend
size_t index = 0;
- ELFSegmentFactory::const_iterator seg = pBackend.elfSegmentTable().begin(),
- segEnd = pBackend.elfSegmentTable().end();
+ ELFSegmentFactory::const_iterator seg = target().elfSegmentTable().begin(),
+ segEnd = target().elfSegmentTable().end();
for (; seg != segEnd; ++seg, ++index) {
phdr[index].p_type = (*seg).type();
phdr[index].p_flags = (*seg).flag();
@@ -314,174 +312,61 @@
}
}
-/// emitELF32ShStrTab - emit section string table
-void ELFWriter::emitELF32ShStrTab(Output& pOutput, MCLinker& pLinker) const
+/// emitELFShStrTab - emit section string table
+void
+ELFWriter::emitELFShStrTab(const LDSection& pShStrTab, const Module& pModule,
+ MemoryArea& pOutput)
{
- uint64_t shstroffset = getELF32LastStartOffset(pOutput);
-
- // get shstrtab
- LDSection& shstrtab = pLinker.getOrCreateOutputSectHdr(".shstrtab",
- LDFileFormat::NamePool,
- SHT_STRTAB,
- 0x0);
- if (0 != shstrtab.size())
- llvm::report_fatal_error(".shstrtab has been set.\n");
-
- // compute size
- unsigned int shstrsize = 0;
- LDContext::const_sect_iterator section, sectEnd = pOutput.context()->sectEnd();
- for (section = pOutput.context()->sectBegin(); section != sectEnd; ++section) {
- shstrsize += (*section)->name().size() + 1;
- }
-
- shstrtab.setSize(shstrsize);
- shstrtab.setOffset(shstroffset);
-
// write out data
- MemoryRegion* region = pOutput.memArea()->request(shstrtab.offset(),
- shstrtab.size());
+ MemoryRegion* region = pOutput.request(pShStrTab.offset(), pShStrTab.size());
unsigned char* data = region->start();
- shstrsize = 0;
- for (section = pOutput.context()->sectBegin(); section != sectEnd; ++section) {
- strcpy((char*)(data + shstrsize), (*section)->name().c_str());
+ size_t shstrsize = 0;
+ Module::const_iterator section, sectEnd = pModule.end();
+ for (section = pModule.begin(); section != sectEnd; ++section) {
+ strcpy((char*)(data + shstrsize), (*section)->name().data());
shstrsize += (*section)->name().size() + 1;
}
-
- shstrtab.setKind(LDFileFormat::NamePool);
- shstrtab.setType(llvm::ELF::SHT_STRTAB);
- shstrtab.setFlag(0x0);
- shstrtab.setAddr(0x0);
-}
-
-
-/// emitELF64ShStrTab - emit section string table
-void ELFWriter::emitELF64ShStrTab(Output& pOutput, MCLinker& pLinker) const
-{
- uint64_t shstroffset = getELF64LastStartOffset(pOutput);
-
- // get shstrtab
- LDSection& shstrtab = pLinker.getOrCreateOutputSectHdr(".shstrtab",
- LDFileFormat::NamePool,
- SHT_STRTAB,
- 0x0);
- if (0 != shstrtab.size())
- llvm::report_fatal_error(".shstrtab has been set.\n");
-
- // compute offset
-
- // compute size
- unsigned int shstrsize = 0;
- LDContext::const_sect_iterator section, sectEnd = pOutput.context()->sectEnd();
- for (section = pOutput.context()->sectBegin(); section != sectEnd; ++section) {
- shstrsize += (*section)->name().size() + 1;
- }
-
- shstrtab.setSize(shstrsize);
- shstrtab.setOffset(shstroffset);
-
- // write out data
- MemoryRegion* region = pOutput.memArea()->request(shstrtab.offset(),
- shstrtab.size());
- unsigned char* data = region->start();
- shstrsize = 0;
- for (section = pOutput.context()->sectBegin(); section != sectEnd; ++section) {
- strcpy((char*)(data + shstrsize), (*section)->name().c_str());
- shstrsize += (*section)->name().size() + 1;
- }
-
- shstrtab.setKind(LDFileFormat::NamePool);
- shstrtab.setType(llvm::ELF::SHT_STRTAB);
- shstrtab.setFlag(0x0);
- shstrtab.setAddr(0x0);
}
/// emitSectionData
void
-ELFWriter::emitSectionData(const Layout& pLayout,
- const LDSection& pSection,
+ELFWriter::emitSectionData(const LDSection& pSection,
MemoryRegion& pRegion) const
{
- const SectionData* data = pSection.getSectionData();
- SectionData::const_iterator fragIter, fragEnd = data->end();
- size_t cur_offset = 0;
- for (fragIter = data->begin(); fragIter != fragEnd; ++fragIter) {
- size_t size = computeFragmentSize(pLayout, *fragIter);
- switch(fragIter->getKind()) {
- case Fragment::Region: {
- const RegionFragment& region_frag = llvm::cast<RegionFragment>(*fragIter);
- const uint8_t* from = region_frag.getRegion().start();
- memcpy(pRegion.getBuffer(cur_offset), from, size);
- break;
- }
- case Fragment::Alignment: {
- // TODO: emit values with different sizes (> 1 byte), and emit nops
- AlignFragment& align_frag = llvm::cast<AlignFragment>(*fragIter);
- uint64_t count = size / align_frag.getValueSize();
- switch (align_frag.getValueSize()) {
- case 1u:
- std::memset(pRegion.getBuffer(cur_offset),
- align_frag.getValue(),
- count);
- break;
- default:
- llvm::report_fatal_error("unsupported value size for align fragment emission yet.\n");
- break;
- }
- break;
- }
- case Fragment::Fillment: {
- FillFragment& fill_frag = llvm::cast<FillFragment>(*fragIter);
- if (0 == size ||
- 0 == fill_frag.getValueSize() ||
- 0 == fill_frag.getSize()) {
- // ignore virtual fillment
- break;
- }
-
- uint64_t num_tiles = fill_frag.getSize() / fill_frag.getValueSize();
- for (uint64_t i = 0; i != num_tiles; ++i) {
- std::memset(pRegion.getBuffer(cur_offset),
- fill_frag.getValue(),
- fill_frag.getValueSize());
- }
- break;
- }
- case Fragment::Relocation:
- llvm::report_fatal_error("relocation fragment should not be in a regular section.\n");
- break;
- case Fragment::Target:
- llvm::report_fatal_error("Target fragment should not be in a regular section.\n");
- break;
- default:
- llvm::report_fatal_error("invalid fragment should not be in a regular section.\n");
- break;
- }
- cur_offset += size;
+ const SectionData* sd = NULL;
+ switch (pSection.kind()) {
+ case LDFileFormat::Relocation:
+ return;
+ case LDFileFormat::EhFrame:
+ sd = &pSection.getEhFrame()->getSectionData();
+ break;
+ default:
+ sd = pSection.getSectionData();
+ break;
}
+ emitSectionData(*sd, pRegion);
}
/// emitRelocation
-void ELFWriter::emitRelocation(const Layout& pLayout,
- const Output& pOutput,
+void ELFWriter::emitRelocation(const LinkerConfig& pConfig,
const LDSection& pSection,
MemoryRegion& pRegion) const
{
- const SectionData* sect_data = pSection.getSectionData();
+ const RelocData* sect_data = pSection.getRelocData();
assert(NULL != sect_data && "SectionData is NULL in emitRelocation!");
if (pSection.type() == SHT_REL)
- emitRel(pLayout, pOutput, *sect_data, pRegion);
+ emitRel(pConfig, *sect_data, pRegion);
else if (pSection.type() == SHT_RELA)
- emitRela(pLayout, pOutput, *sect_data, pRegion);
+ emitRela(pConfig, *sect_data, pRegion);
else
llvm::report_fatal_error("unsupported relocation section type!");
}
/// emitRel
-void ELFWriter::emitRel(const Layout& pLayout,
- const Output& pOutput,
- const SectionData& pSectionData,
+void ELFWriter::emitRel(const LinkerConfig& pConfig,
+ const RelocData& pRelocData,
MemoryRegion& pRegion) const
{
Elf32_Rel* rel = reinterpret_cast<Elf32_Rel*>(pRegion.start());
@@ -489,23 +374,21 @@
Relocation* relocation = 0;
FragmentRef* frag_ref = 0;
- for (SectionData::const_iterator it = pSectionData.begin(),
- ie = pSectionData.end(); it != ie; ++it, ++rel) {
+ for (RelocData::const_iterator it = pRelocData.begin(),
+ ie = pRelocData.end(); it != ie; ++it, ++rel) {
relocation = &(llvm::cast<Relocation>(*it));
frag_ref = &(relocation->targetRef());
- if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec) {
+ if(LinkerConfig::DynObj == pConfig.codeGenType() ||
+ LinkerConfig::Exec == pConfig.codeGenType()) {
rel->r_offset = static_cast<Elf32_Addr>(
frag_ref->frag()->getParent()->getSection().addr() +
- pLayout.getOutputOffset(*frag_ref));
+ frag_ref->getOutputOffset());
}
else {
- rel->r_offset = static_cast<Elf32_Addr>(
- frag_ref->frag()->getParent()->getSection().offset() +
- pLayout.getOutputOffset(*frag_ref));
+ rel->r_offset = static_cast<Elf32_Addr>(frag_ref->getOutputOffset());
}
-
Elf32_Word Index;
if( relocation->symInfo() == NULL )
Index = 0;
@@ -518,9 +401,8 @@
}
/// emitRela
-void ELFWriter::emitRela(const Layout& pLayout,
- const Output& pOutput,
- const SectionData& pSectionData,
+void ELFWriter::emitRela(const LinkerConfig& pConfig,
+ const RelocData& pRelocData,
MemoryRegion& pRegion) const
{
Elf32_Rela* rel = reinterpret_cast<Elf32_Rela*>(pRegion.start());
@@ -528,21 +410,20 @@
Relocation* relocation = 0;
FragmentRef* frag_ref = 0;
- for (SectionData::const_iterator it = pSectionData.begin(),
- ie = pSectionData.end(); it != ie; ++it, ++rel) {
+ for (RelocData::const_iterator it = pRelocData.begin(),
+ ie = pRelocData.end(); it != ie; ++it, ++rel) {
relocation = &(llvm::cast<Relocation>(*it));
frag_ref = &(relocation->targetRef());
- if(pOutput.type() == Output::DynObj || pOutput.type() == Output::Exec) {
+ if(LinkerConfig::DynObj == pConfig.codeGenType() ||
+ LinkerConfig::Exec == pConfig.codeGenType()) {
rel->r_offset = static_cast<Elf32_Addr>(
frag_ref->frag()->getParent()->getSection().addr() +
- pLayout.getOutputOffset(*frag_ref));
+ frag_ref->getOutputOffset());
}
else {
- rel->r_offset = static_cast<Elf32_Addr>(
- frag_ref->frag()->getParent()->getSection().offset() +
- pLayout.getOutputOffset(*frag_ref));
+ rel->r_offset = static_cast<Elf32_Addr>(frag_ref->getOutputOffset());
}
Elf32_Word Index;
@@ -592,29 +473,32 @@
}
/// getSectLink - compute ElfXX_Shdr::sh_link
-uint64_t ELFWriter::getSectLink(const LDSection& pSection, const Output& pOutput) const
+uint64_t ELFWriter::getSectLink(const LDSection& pSection,
+ const LinkerConfig& pConfig) const
{
- const LDContext* context = pOutput.context();
if (llvm::ELF::SHT_SYMTAB == pSection.type())
- return context->getSectionIdx(".strtab");
+ return target().getOutputFormat()->getStrTab().index();
if (llvm::ELF::SHT_DYNSYM == pSection.type())
- return context->getSectionIdx(".dynstr");
+ return target().getOutputFormat()->getDynStrTab().index();
if (llvm::ELF::SHT_DYNAMIC == pSection.type())
- return context->getSectionIdx(".dynstr");
+ return target().getOutputFormat()->getDynStrTab().index();
if (llvm::ELF::SHT_HASH == pSection.type())
- return context->getSectionIdx(".dynsym");
+ return target().getOutputFormat()->getDynSymTab().index();
if (llvm::ELF::SHT_REL == pSection.type() ||
llvm::ELF::SHT_RELA == pSection.type()) {
- if (pOutput.type() == Output::Object)
- return context->getSectionIdx(".symtab");
+ if (LinkerConfig::Object == pConfig.codeGenType())
+ return target().getOutputFormat()->getSymTab().index();
else
- return context->getSectionIdx(".dynsym");
+ return target().getOutputFormat()->getDynSymTab().index();
}
+ // FIXME: currently we link ARM_EXIDX section to output text section here
+ if (llvm::ELF::SHT_ARM_EXIDX == pSection.type())
+ return target().getOutputFormat()->getText().index();
return llvm::ELF::SHN_UNDEF;
}
/// getSectInfo - compute ElfXX_Shdr::sh_info
-uint64_t ELFWriter::getSectInfo(const LDSection& pSection, const Output& pOutput) const
+uint64_t ELFWriter::getSectInfo(const LDSection& pSection) const
{
const LDSection* info_link = pSection.getLink();
if (NULL == info_link)
@@ -623,18 +507,89 @@
}
/// getELF32LastStartOffset
-uint64_t ELFWriter::getELF32LastStartOffset(const Output& pOutput) const
+uint64_t ELFWriter::getELF32LastStartOffset(const Module& pModule) const
{
- LDSection* lastSect = pOutput.context()->getSectionTable().back();
+ const LDSection* lastSect = pModule.back();
assert(lastSect != NULL);
return Align<32>(lastSect->offset() + lastSect->size());
}
/// getELF64LastStartOffset
-uint64_t ELFWriter::getELF64LastStartOffset(const Output& pOutput) const
+uint64_t ELFWriter::getELF64LastStartOffset(const Module& pModule) const
{
- LDSection* lastSect = pOutput.context()->getSectionTable().back();
+ const LDSection* lastSect = pModule.back();
assert(lastSect != NULL);
return Align<64>(lastSect->offset() + lastSect->size());
}
+/// emitSectionData
+void
+ELFWriter::emitSectionData(const SectionData& pSD, MemoryRegion& pRegion) const
+{
+ SectionData::const_iterator fragIter, fragEnd = pSD.end();
+ size_t cur_offset = 0;
+ for (fragIter = pSD.begin(); fragIter != fragEnd; ++fragIter) {
+ size_t size = fragIter->size();
+ switch(fragIter->getKind()) {
+ case Fragment::Region: {
+ const RegionFragment& region_frag = llvm::cast<RegionFragment>(*fragIter);
+ const uint8_t* from = region_frag.getRegion().start();
+ memcpy(pRegion.getBuffer(cur_offset), from, size);
+ break;
+ }
+ case Fragment::Alignment: {
+ // TODO: emit values with different sizes (> 1 byte), and emit nops
+ AlignFragment& align_frag = llvm::cast<AlignFragment>(*fragIter);
+ uint64_t count = size / align_frag.getValueSize();
+ switch (align_frag.getValueSize()) {
+ case 1u:
+ std::memset(pRegion.getBuffer(cur_offset),
+ align_frag.getValue(),
+ count);
+ break;
+ default:
+ llvm::report_fatal_error("unsupported value size for align fragment emission yet.\n");
+ break;
+ }
+ break;
+ }
+ case Fragment::Fillment: {
+ FillFragment& fill_frag = llvm::cast<FillFragment>(*fragIter);
+ if (0 == size ||
+ 0 == fill_frag.getValueSize() ||
+ 0 == fill_frag.size()) {
+ // ignore virtual fillment
+ break;
+ }
+
+ uint64_t num_tiles = fill_frag.size() / fill_frag.getValueSize();
+ for (uint64_t i = 0; i != num_tiles; ++i) {
+ std::memset(pRegion.getBuffer(cur_offset),
+ fill_frag.getValue(),
+ fill_frag.getValueSize());
+ }
+ break;
+ }
+ case Fragment::Stub: {
+ Stub& stub_frag = llvm::cast<Stub>(*fragIter);
+ memcpy(pRegion.getBuffer(cur_offset), stub_frag.getContent(), size);
+ break;
+ }
+ case Fragment::Null: {
+ assert(0x0 == size);
+ break;
+ }
+ case Fragment::Relocation:
+ llvm::report_fatal_error("relocation fragment should not be in a regular section.\n");
+ break;
+ case Fragment::Target:
+ llvm::report_fatal_error("Target fragment should not be in a regular section.\n");
+ break;
+ default:
+ llvm::report_fatal_error("invalid fragment should not be in a regular section.\n");
+ break;
+ }
+ cur_offset += size;
+ }
+}
+
diff --git a/lib/LD/EhFrame.cpp b/lib/LD/EhFrame.cpp
index bc5ed1d..df61c24 100644
--- a/lib/LD/EhFrame.cpp
+++ b/lib/LD/EhFrame.cpp
@@ -6,353 +6,83 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#include <mcld/LD/EhFrame.h>
-
-#include <llvm/Support/Dwarf.h>
-#include <llvm/Support/Host.h>
-
-#include <mcld/MC/MCLinker.h>
-#include <mcld/Target/TargetLDBackend.h>
-#include <mcld/Support/MsgHandling.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Object/ObjectBuilder.h>
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
+// EhFrame::CIE
+//===----------------------------------------------------------------------===//
+EhFrame::CIE::CIE(MemoryRegion& pRegion)
+ : RegionFragment(pRegion) {
+}
+
+//===----------------------------------------------------------------------===//
+// EhFrame::FDE
+//===----------------------------------------------------------------------===//
+EhFrame::FDE::FDE(MemoryRegion& pRegion,
+ const EhFrame::CIE& pCIE,
+ uint32_t pDataStart)
+ : RegionFragment(pRegion),
+ m_CIE(pCIE),
+ m_DataStart(pDataStart) {
+}
+
+//===----------------------------------------------------------------------===//
// EhFrame
-EhFrame::EhFrame()
- : m_fCanRecognizeAll(true) {
+//===----------------------------------------------------------------------===//
+EhFrame::EhFrame(LDSection& pSection)
+ : m_Section(pSection),
+ m_pSectionData(NULL) {
+ m_pSectionData = SectionData::Create(pSection);
}
EhFrame::~EhFrame()
{
+ // Since all CIEs, FDEs and regular fragments are stored in iplist, iplist
+ // will delete the fragments and we do not need to handle with it.
}
-uint64_t EhFrame::readEhFrame(Layout& pLayout,
- const TargetLDBackend& pBackend,
- SectionData& pSD,
- const Input& pInput,
- LDSection& pSection,
- MemoryArea& pArea)
+void EhFrame::addFragment(RegionFragment& pFrag)
{
- MemoryRegion* region = pArea.request(
- pInput.fileOffset() + pSection.offset(), pSection.size());
- // an empty .eh_frame
- if (NULL == region) {
- return 0;
- }
+ uint32_t offset = 0;
+ if (!m_pSectionData->empty())
+ offset = m_pSectionData->back().getOffset() + m_pSectionData->back().size();
- ConstAddress eh_start = region->start();
- ConstAddress eh_end = region->end();
- ConstAddress p = eh_start;
-
- // read the Length filed
- uint32_t len = readVal(p, pBackend.isLittleEndian());
-
- // This CIE is a terminator if the Length field is 0, return 0 to handled it
- // as an ordinary input.
- if (0 == len) {
- pArea.release(region);
- return 0;
- }
-
- if (0xffffffff == len) {
- debug(diag::debug_eh_unsupport) << pInput.name();
- pArea.release(region);
- m_fCanRecognizeAll = false;
- return 0;
- }
-
- // record the order of the CIE and FDE fragments
- FragListType frag_list;
-
- while (p < eh_end) {
-
- if (eh_end - p < 4) {
- debug(diag::debug_eh_unsupport) << pInput.name();
- m_fCanRecognizeAll = false;
- break;
- }
- // read the Length field
- len = readVal(p, pBackend.isLittleEndian());
- p += 4;
-
- // the zero length entry should be the end of the section
- if (0 == len) {
- if (p < eh_end) {
- debug(diag::debug_eh_unsupport) << pInput.name();
- m_fCanRecognizeAll = false;
- }
- break;
- }
- if (0xffffffff == len) {
- debug(diag::debug_eh_unsupport) << pInput.name();
- m_fCanRecognizeAll = false;
- break;
- }
-
- if (eh_end - p < 4) {
- debug(diag::debug_eh_unsupport) << pInput.name();
- m_fCanRecognizeAll = false;
- break;
- }
-
- // compute the section offset of this entry
- uint32_t ent_offset = static_cast<uint32_t>(p - eh_start - 4);
-
- // get the MemoryRegion for this entry
- MemoryRegion* ent_region = pArea.request(
- pInput.fileOffset() + pSection.offset() + ent_offset, len + 4);
-
- // create and add a CIE or FDE entry
- uint32_t id = readVal(p, pBackend.isLittleEndian());
- // CIE
- if (0 == id) {
- if (!addCIE(*ent_region, pBackend, frag_list)) {
- m_fCanRecognizeAll = false;
- pArea.release(ent_region);
- break;
- }
- }
-
- // FDE
- else {
- if (!addFDE(*ent_region, pBackend, frag_list)) {
- m_fCanRecognizeAll = false;
- pArea.release(ent_region);
- break;
- }
- }
- p += len;
- }
-
- if (!m_fCanRecognizeAll) {
- debug(diag::debug_eh_unsupport) << pInput.name();
- pArea.release(region);
- deleteFragments(frag_list, pArea);
- return 0;
- }
-
- // append all CIE and FDE fragments to Layout after we successfully read
- // this eh_frame
- size_t section_size = 0;
- for (FragListType::iterator it = frag_list.begin();
- it != frag_list.end(); ++it)
- section_size += pLayout.appendFragment(**it, pSD, pSection.align());
-
- pArea.release(region);
- return section_size;
+ m_pSectionData->getFragmentList().push_back(&pFrag);
+ pFrag.setOffset(offset);
}
-bool EhFrame::addCIE(MemoryRegion& pRegion,
- const TargetLDBackend& pBackend,
- FragListType& pFragList)
+void EhFrame::addCIE(EhFrame::CIE& pCIE)
{
- ConstAddress cie_start = pRegion.start();
- ConstAddress cie_end = pRegion.end();
- ConstAddress p = cie_start;
-
- // skip the Length (4 byte) and CIE ID (4 byte) fields
- p += 8;
-
- // the version should be 1
- if (1 != *p) {
- return false;
- }
- ++p;
-
- // get the Augumentation String
- ConstAddress aug_str = p;
- ConstAddress aug_str_end = static_cast<ConstAddress>(
- memchr(p, '\0', cie_end - p));
-
- // skip the Augumentation String field
- p = aug_str_end + 1;
-
- // skip the Code Alignment Factor
- if (!skipLEB128(&p, cie_end)) {
- return false;
- }
- // skip the Data Alignment Factor
- if (!skipLEB128(&p, cie_end)) {
- return false;
- }
- // skip the Return Address Register
- if (cie_end - p < 1) {
- return false;
- }
- ++p;
-
- // the Augmentation String start with 'eh' is a CIE from gcc before 3.0,
- // in LSB Core Spec 3.0RC1. We do not support it.
- if (aug_str[0] == 'e' && aug_str[1] == 'h') {
- return false;
- }
-
- // parse the Augmentation String to get the FDE encodeing if 'z' existed
- std::string aug_str_data;
- uint8_t fde_encoding = llvm::dwarf::DW_EH_PE_absptr;
- if (*aug_str == 'z') {
-
- aug_str_data += *aug_str;
- ++aug_str;
-
- // skip the Augumentation Data Length
- if (!skipLEB128(&p, cie_end)) {
- return false;
- }
-
- while (aug_str != aug_str_end) {
- switch (*aug_str) {
- default:
- return false;
-
- // LDSA encoding (1 byte)
- case 'L':
- if (cie_end - p < 1) {
- return false;
- }
- ++p;
- break;
-
- // Two arguments, the first one represents the encoding of the second
- // argument (1 byte). The second one is the address of personality
- // routine.
- case 'P': {
- // the first argument
- if (cie_end - p < 1) {
- return false;
- }
- uint8_t per_encode = *p;
- ++p;
- // get the length of the second argument
- uint32_t per_length = 0;
- if (0x60 == (per_encode & 0x60)) {
- return false;
- }
- switch (per_encode & 7) {
- default:
- return false;
- case llvm::dwarf::DW_EH_PE_udata2:
- per_length = 2;
- break;
- case llvm::dwarf::DW_EH_PE_udata4:
- per_length = 4;
- break;
- case llvm::dwarf::DW_EH_PE_udata8:
- per_length = 8;
- break;
- case llvm::dwarf::DW_EH_PE_absptr:
- per_length = pBackend.bitclass() / 8;
- break;
- }
- // skip the alignment
- if (llvm::dwarf::DW_EH_PE_aligned == (per_encode & 0xf0)) {
- uint32_t per_align = p - cie_end;
- per_align += per_length - 1;
- per_align &= ~(per_length -1);
- if (static_cast<uint32_t>(cie_end - p) < per_align) {
- return false;
- }
- p += per_align;
- }
- // skip the second argument
- if (static_cast<uint32_t>(cie_end - p) < per_length) {
- return false;
- }
- p += per_length;
- }
- break;
-
- // FDE encoding (1 byte)
- case 'R':
- if (cie_end - p < 1) {
- return false;
- }
- fde_encoding = *p;
- switch (fde_encoding & 7) {
- case llvm::dwarf::DW_EH_PE_udata2:
- case llvm::dwarf::DW_EH_PE_udata4:
- case llvm::dwarf::DW_EH_PE_udata8:
- case llvm::dwarf::DW_EH_PE_absptr:
- break;
- default:
- return false;
- }
- ++p;
- break;
- } // end switch
- aug_str_data += *aug_str;
- ++aug_str;
- } // end while
- }
-
- note(diag::note_eh_cie) << pRegion.size()
- << aug_str_data
- << (fde_encoding & 7);
-
- // create and push back the CIE entry
- CIE* entry = new CIE(pRegion, fde_encoding);
- m_CIEs.push_back(entry);
- pFragList.push_back(static_cast<Fragment*>(entry));
- return true;
+ m_CIEs.push_back(&pCIE);
+ addFragment(pCIE);
}
-bool EhFrame::addFDE(MemoryRegion& pRegion,
- const TargetLDBackend& pBackend,
- FragListType& pFragList)
+void EhFrame::addFDE(EhFrame::FDE& pFDE)
{
- ConstAddress fde_start = pRegion.start();
- ConstAddress fde_end = pRegion.end();
- ConstAddress p = fde_start;
-
- // skip the Length (4 byte) and CIE Pointer (4 byte) fields
- p += 8;
-
- // get the entry offset of the PC Begin
- if (fde_end - p < 1) {
- return false;
- }
- FDE::Offset pc_offset = static_cast<FDE::Offset>(p - fde_start);
-
- note(diag::note_eh_fde) << pRegion.size() << pc_offset;
- // create and push back the FDE entry
- FDE* entry = new FDE(pRegion, **(m_CIEs.end() -1), pc_offset);
- m_FDEs.push_back(entry);
- pFragList.push_back(static_cast<Fragment*>(entry));
- return true;
+ m_FDEs.push_back(&pFDE);
+ addFragment(pFDE);
}
-uint32_t EhFrame::readVal(ConstAddress pAddr, bool pIsTargetLittleEndian)
+EhFrame& EhFrame::merge(EhFrame& pOther)
{
- const uint32_t* p = reinterpret_cast<const uint32_t*>(pAddr);
- uint32_t val = *p;
+ ObjectBuilder::MoveSectionData(pOther.getSectionData(), *m_pSectionData);
- // byte swapping if the host and target have different endian
- if (llvm::sys::isLittleEndianHost() != pIsTargetLittleEndian)
- val = bswap32(val);
- return val;
-}
+ m_CIEs.reserve(pOther.numOfCIEs() + m_CIEs.size());
+ for (cie_iterator cie = pOther.cie_begin(); cie != pOther.cie_end(); ++cie)
+ m_CIEs.push_back(*cie);
-bool EhFrame::skipLEB128(ConstAddress* pp, ConstAddress pend)
-{
- for (ConstAddress p = *pp; p < pend; ++p) {
- if (0 == (*p & 0x80)) {
- *pp = p + 1;
- return true;
- }
- }
- return false;
-}
+ m_FDEs.reserve(pOther.numOfFDEs() + m_FDEs.size());
+ for (fde_iterator fde = pOther.fde_begin(); fde != pOther.fde_end(); ++fde)
+ m_FDEs.push_back(*fde);
-void EhFrame::deleteFragments(FragListType& pList, MemoryArea& pArea)
-{
- RegionFragment* frag = NULL;
- for (FragListType::iterator it = pList.begin(); it != pList.end(); ++it) {
- frag = static_cast<RegionFragment*>(*it);
- pArea.release(&(frag->getRegion()));
- delete *it;
- }
- pList.clear();
+ pOther.m_CIEs.clear();
+ pOther.m_FDEs.clear();
+ return *this;
}
diff --git a/lib/LD/EhFrameHdr.cpp b/lib/LD/EhFrameHdr.cpp
index 8806af4..4c0d59c 100644
--- a/lib/LD/EhFrameHdr.cpp
+++ b/lib/LD/EhFrameHdr.cpp
@@ -8,17 +8,118 @@
//===----------------------------------------------------------------------===//
#include <mcld/LD/EhFrameHdr.h>
-using namespace mcld;
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/LDSection.h>
-//==========================
-// EhFrameHdr
-EhFrameHdr::EhFrameHdr(const EhFrame& pEhFrameData,
- const LDSection& pEhFrameSect,
- LDSection& pEhFrameHdrSect)
- : m_EhFrameData(pEhFrameData),
- m_EhFrameSect(pEhFrameSect),
- m_EhFrameHdrSect(pEhFrameHdrSect)
+#include <llvm/Support/Dwarf.h>
+#include <llvm/Support/DataTypes.h>
+
+#include <algorithm>
+#include <cstring>
+
+using namespace mcld;
+using namespace llvm::dwarf;
+
+//===----------------------------------------------------------------------===//
+// Helper Function
+//===----------------------------------------------------------------------===//
+namespace bit32 {
+
+typedef std::pair<SizeTraits<32>::Address, SizeTraits<32>::Address> Entry;
+
+bool EntryCompare(const Entry& pX, const Entry& pY)
+{ return (pX.first < pY.first); }
+
+} // bit32 namespace
+
+//===----------------------------------------------------------------------===//
+// Template Specification Functions
+//===----------------------------------------------------------------------===//
+/// emitOutput<32> - write out eh_frame_hdr
+template<>
+void EhFrameHdr::emitOutput<32>(MemoryArea& pOutput)
{
+ MemoryRegion* ehframehdr_region =
+ pOutput.request(m_EhFrameHdr.offset(), m_EhFrameHdr.size());
+
+ MemoryRegion* ehframe_region =
+ pOutput.request(m_EhFrame.offset(),
+ m_EhFrame.size());
+
+ uint8_t* data = (uint8_t*)ehframehdr_region->start();
+ // version
+ data[0] = 1;
+ // eh_frame_ptr_enc
+ data[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
+
+ // eh_frame_ptr
+ uint32_t* eh_frame_ptr = (uint32_t*)(data + 4);
+ *eh_frame_ptr = m_EhFrame.addr() - (m_EhFrameHdr.addr() + 4);
+
+ // fde_count
+ uint32_t* fde_count = (uint32_t*)(data + 8);
+ if (m_EhFrame.hasEhFrame())
+ *fde_count = 0;
+ else
+ *fde_count = m_EhFrame.getEhFrame()->numOfFDEs();
+
+ if (0 != *fde_count) {
+ // fde_count_enc
+ data[2] = DW_EH_PE_udata4;
+ // table_enc
+ data[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
+
+ }
+ else {
+ // fde_count_enc
+ data[2] = DW_EH_PE_omit;
+ // table_enc
+ data[3] = DW_EH_PE_omit;
+ }
+
+ if (0 != *fde_count) {
+
+ // prepare the binary search table
+ typedef std::vector<bit32::Entry> SearchTableType;
+ SearchTableType search_table;
+ MemoryRegion* ehframe_region =
+ pOutput.request(m_EhFrame.offset(), m_EhFrame.size());
+ EhFrame::const_fde_iterator fde, fde_end = m_EhFrame.getEhFrame()->fde_end();
+ for(fde = m_EhFrame.getEhFrame()->fde_begin(); fde != fde_end; ++fde) {
+ assert(*fde != NULL);
+ SizeTraits<32>::Offset offset;
+ SizeTraits<32>::Address fde_pc;
+ SizeTraits<32>::Address fde_addr;
+ offset = (*fde)->getOffset();
+ fde_pc = computePCBegin(**fde, *ehframe_region);
+ fde_addr = m_EhFrame.addr() + offset;
+ search_table.push_back(std::make_pair(fde_pc, fde_addr));
+ }
+ pOutput.release(ehframe_region);
+
+ std::sort(search_table.begin(), search_table.end(), bit32::EntryCompare);
+
+ // write out the binary search table
+ uint32_t* bst = (uint32_t*)(data + 12);
+ SearchTableType::const_iterator entry, entry_end = search_table.end();
+ size_t id = 0;
+ for (entry = search_table.begin(); entry != entry_end; ++entry) {
+ bst[id++] = (*entry).first - m_EhFrameHdr.addr();
+ bst[id++] = (*entry).second - m_EhFrameHdr.addr();
+ }
+ }
+ pOutput.release(ehframehdr_region);
+ pOutput.release(ehframe_region);
+}
+
+//===----------------------------------------------------------------------===//
+// EhFrameHdr
+//===----------------------------------------------------------------------===//
+
+EhFrameHdr::EhFrameHdr(LDSection& pEhFrameHdr, const LDSection& pEhFrame)
+ : m_EhFrameHdr(pEhFrameHdr), m_EhFrame(pEhFrame) {
}
EhFrameHdr::~EhFrameHdr()
@@ -35,15 +136,69 @@
/// uint32_t : fde_count
/// __________________________ when fde_count > 0
/// <uint32_t, uint32_t>+ : binary search table
-
/// sizeOutput - base on the fde count to size output
void EhFrameHdr::sizeOutput()
{
size_t size = 12;
- if (m_EhFrameData.canRecognizeAllEhFrame()) {
- size_t fde_count = m_EhFrameData.getFDECount();
- size += 8 * fde_count;
- }
- m_EhFrameHdrSect.setSize(size);
+ if (m_EhFrame.hasEhFrame())
+ size += 8 * m_EhFrame.getEhFrame()->numOfFDEs();
+ m_EhFrameHdr.setSize(size);
}
+/// computePCBegin - return the address of FDE's pc
+/// @ref binutils gold: ehframe.cc:222
+uint32_t EhFrameHdr::computePCBegin(const EhFrame::FDE& pFDE,
+ const MemoryRegion& pEhFrameRegion)
+{
+ uint8_t fde_encoding = pFDE.getCIE().getFDEEncode();
+ unsigned int eh_value = fde_encoding & 0x7;
+
+ // check the size to read in
+ if (eh_value == llvm::dwarf::DW_EH_PE_absptr) {
+ eh_value = DW_EH_PE_udata4;
+ }
+
+ size_t pc_size = 0x0;
+ switch (eh_value) {
+ case DW_EH_PE_udata2:
+ pc_size = 2;
+ break;
+ case DW_EH_PE_udata4:
+ pc_size = 4;
+ break;
+ case DW_EH_PE_udata8:
+ pc_size = 8;
+ break;
+ default:
+ // TODO
+ break;
+ }
+
+ SizeTraits<32>::Address pc = 0x0;
+ const uint8_t* offset = (const uint8_t*) pEhFrameRegion.start() +
+ pFDE.getOffset() +
+ pFDE.getDataStart();
+ std::memcpy(&pc, offset, pc_size);
+
+ // adjust the signed value
+ bool is_signed = (fde_encoding & llvm::dwarf::DW_EH_PE_signed) != 0x0;
+ if (DW_EH_PE_udata2 == eh_value && is_signed)
+ pc = (pc ^ 0x8000) - 0x8000;
+
+ // handle eh application
+ switch (fde_encoding & 0x70)
+ {
+ case DW_EH_PE_absptr:
+ break;
+ case DW_EH_PE_pcrel:
+ pc += m_EhFrame.addr() + pFDE.getOffset() + pFDE.getDataStart();
+ break;
+ case DW_EH_PE_datarel:
+ // TODO
+ break;
+ default:
+ // TODO
+ break;
+ }
+ return pc;
+}
diff --git a/lib/LD/EhFrameReader.cpp b/lib/LD/EhFrameReader.cpp
new file mode 100644
index 0000000..efcec5a
--- /dev/null
+++ b/lib/LD/EhFrameReader.cpp
@@ -0,0 +1,339 @@
+//===- EhFrameReader.cpp --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/EhFrameReader.h>
+
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Support/Dwarf.h>
+
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MsgHandling.h>
+
+using namespace mcld;
+using namespace llvm::dwarf;
+
+//===----------------------------------------------------------------------===//
+// Helper Functions
+//===----------------------------------------------------------------------===//
+/// skip_LEB128 - skip the first LEB128 encoded value from *pp, update *pp
+/// to the next character.
+/// @return - false if we ran off the end of the string.
+/// @ref - GNU gold 1.11, ehframe.h, Eh_frame::skip_leb128.
+static bool
+skip_LEB128(EhFrameReader::ConstAddress* pp, EhFrameReader::ConstAddress pend)
+{
+ for (EhFrameReader::ConstAddress p = *pp; p < pend; ++p) {
+ if (0x0 == (*p & 0x80)) {
+ *pp = p + 1;
+ return true;
+ }
+ }
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// EhFrameReader
+//===----------------------------------------------------------------------===//
+template<> EhFrameReader::Token
+EhFrameReader::scan<true>(ConstAddress pHandler,
+ uint64_t pOffset,
+ const MemoryRegion& pData) const
+{
+ Token result;
+ result.file_off = pOffset;
+
+ const uint32_t* data = (const uint32_t*)pHandler;
+ size_t cur_idx = 0;
+
+ // Length Field
+ uint32_t length = data[cur_idx++];
+ if (0x0 == length) {
+ // terminator
+ result.kind = Terminator;
+ result.data_off = 4;
+ result.size = 4;
+ return result;
+ }
+
+ // Extended Field
+ uint64_t extended = 0x0;
+ if (0xFFFFFFFF == length) {
+ extended = data[cur_idx++];
+ extended <<= 32;
+ extended |= data[cur_idx++];
+ result.size = extended + 12;
+ result.data_off = 16;
+ }
+ else {
+ result.size = length + 4;
+ result.data_off = 8;
+ }
+
+ // ID Field
+ uint32_t ID = data[cur_idx++];
+ if (0x0 == ID)
+ result.kind = CIE;
+ else
+ result.kind = FDE;
+
+ return result;
+}
+
+template<>
+bool EhFrameReader::read<32, true>(Input& pInput, EhFrame& pEhFrame)
+{
+ // Alphabet:
+ // {CIE, FDE, CIEt}
+ //
+ // Regular Expression:
+ // (CIE FDE*)+ CIEt
+ //
+ // Autometa:
+ // S = {Q0, Q1, Q2}, Start = Q0, Accept = Q2
+ //
+ // FDE
+ // +---+
+ // CIE \ / CIEt
+ // Q0 -------> Q1 -------> Q2
+ // | / \ ^
+ // | +---+ |
+ // | CIE |
+ // +-----------------------+
+ // CIEt
+ const State autometa[NumOfStates][NumOfTokenKinds] = {
+ // CIE FDE Term Unknown
+ { Q1, Reject, Accept, Reject }, // Q0
+ { Q1, Q1, Accept, Reject }, // Q1
+ };
+
+ const Action transition[NumOfStates][NumOfTokenKinds] = {
+ /* CIE FDE Term Unknown */
+ { addCIE, reject, addTerm, reject}, // Q0
+ { addCIE, addFDE, addTerm, reject}, // Q1
+ };
+
+ // get file offset and address
+ LDSection& section = pEhFrame.getSection();
+ uint64_t file_off = pInput.fileOffset() + section.offset();
+ MemoryRegion* sect_reg =
+ pInput.memArea()->request(file_off, section.size());
+ ConstAddress handler = (ConstAddress)sect_reg->start();
+
+ State cur_state = Q0;
+ while (Reject != cur_state && Accept != cur_state) {
+
+ Token token = scan<true>(handler, file_off, *sect_reg);
+ MemoryRegion* entry = pInput.memArea()->request(token.file_off, token.size);
+
+ if (!transition[cur_state][token.kind](pEhFrame, *entry, token)) {
+ // fail to scan
+ debug(diag::debug_cannot_scan_eh) << pInput.name();
+ return false;
+ }
+
+ file_off += token.size;
+ handler += token.size;
+
+ if (handler == sect_reg->end())
+ cur_state = Accept;
+ else if (handler > sect_reg->end()) {
+ cur_state = Reject;
+ }
+ else
+ cur_state = autometa[cur_state][token.kind];
+ } // end of while
+
+ if (Reject == cur_state) {
+ // fail to parse
+ debug(diag::debug_cannot_parse_eh) << pInput.name();
+ return false;
+ }
+ return true;
+}
+
+bool EhFrameReader::addCIE(EhFrame& pEhFrame,
+ MemoryRegion& pRegion,
+ const EhFrameReader::Token& pToken)
+{
+ // skip Length, Extended Length and CIE ID.
+ ConstAddress handler = pRegion.start() + pToken.data_off;
+ ConstAddress cie_end = pRegion.end();
+
+ // the version should be 1 or 3
+ uint8_t version = *handler++;
+ if (1 != version && 3 != version) {
+ return false;
+ }
+
+ // Set up the Augumentation String
+ ConstAddress aug_str_front = handler;
+ ConstAddress aug_str_back = static_cast<ConstAddress>(
+ memchr(aug_str_front, '\0', cie_end - aug_str_front));
+ if (NULL == aug_str_back) {
+ return false;
+ }
+
+ llvm::StringRef augment((const char*)aug_str_front);
+
+ // skip the Augumentation String field
+ handler = aug_str_back + 1;
+
+ // skip the Code Alignment Factor
+ if (!skip_LEB128(&handler, cie_end)) {
+ return false;
+ }
+ // skip the Data Alignment Factor
+ if (!skip_LEB128(&handler, cie_end)) {
+ return false;
+ }
+ // skip the Return Address Register
+ if (cie_end - handler < 1) {
+ return false;
+ }
+ ++handler;
+
+ // the Augmentation String start with 'eh' is a CIE from gcc before 3.0,
+ // in LSB Core Spec 3.0RC1. We do not support it.
+ if (augment[0] == 'e' && augment[1] == 'h') {
+ return false;
+ }
+
+ // parse the Augmentation String to get the FDE encodeing if 'z' existed
+ uint8_t fde_encoding = llvm::dwarf::DW_EH_PE_absptr;
+ if ('z' == augment[0]) {
+
+ // skip the Augumentation Data Length
+ if (!skip_LEB128(&handler, cie_end)) {
+ return false;
+ }
+
+ // parse the Augmentation String
+ for (size_t i = 1; i < augment.size(); ++i) {
+ switch (augment[i]) {
+ // LDSA encoding (1 byte)
+ case 'L': {
+ if (cie_end - handler < 1) {
+ return false;
+ }
+ ++handler;
+ break;
+ }
+ // Two arguments, the first one represents the encoding of the second
+ // argument (1 byte). The second one is the address of personality
+ // routine.
+ case 'P': {
+ // the first argument
+ if (cie_end - handler < 1) {
+ return false;
+ }
+ uint8_t per_encode = *handler;
+ ++handler;
+ // get the length of the second argument
+ uint32_t per_length = 0;
+ if (0x60 == (per_encode & 0x60)) {
+ return false;
+ }
+ switch (per_encode & 7) {
+ default:
+ return false;
+ case llvm::dwarf::DW_EH_PE_udata2:
+ per_length = 2;
+ break;
+ case llvm::dwarf::DW_EH_PE_udata4:
+ per_length = 4;
+ break;
+ case llvm::dwarf::DW_EH_PE_udata8:
+ per_length = 8;
+ break;
+ case llvm::dwarf::DW_EH_PE_absptr:
+ per_length = 4; // pPkg.bitclass / 8;
+ break;
+ }
+ // skip the alignment
+ if (llvm::dwarf::DW_EH_PE_aligned == (per_encode & 0xf0)) {
+ uint32_t per_align = handler - cie_end;
+ per_align += per_length - 1;
+ per_align &= ~(per_length -1);
+ if (static_cast<uint32_t>(cie_end - handler) < per_align) {
+ return false;
+ }
+ handler += per_align;
+ }
+ // skip the second argument
+ if (static_cast<uint32_t>(cie_end - handler) < per_length) {
+ return false;
+ }
+ handler += per_length;
+ break;
+ } // end of case 'P'
+
+ // FDE encoding (1 byte)
+ case 'R': {
+ if (cie_end - handler < 1) {
+ return false;
+ }
+ fde_encoding = *handler;
+ switch (fde_encoding & 7) {
+ case llvm::dwarf::DW_EH_PE_udata2:
+ case llvm::dwarf::DW_EH_PE_udata4:
+ case llvm::dwarf::DW_EH_PE_udata8:
+ case llvm::dwarf::DW_EH_PE_absptr:
+ break;
+ default:
+ return false;
+ }
+ ++handler;
+ break;
+ }
+ default:
+ return false;
+ } // end switch
+ } // the rest chars.
+ } // first char is 'z'
+
+ // create and push back the CIE entry
+ EhFrame::CIE* cie = new EhFrame::CIE(pRegion);
+ cie->setFDEEncode(fde_encoding);
+ pEhFrame.addCIE(*cie);
+ return true;
+}
+
+bool EhFrameReader::addFDE(EhFrame& pEhFrame,
+ MemoryRegion& pRegion,
+ const EhFrameReader::Token& pToken)
+{
+ if (pToken.data_off == pRegion.size())
+ return false;
+
+ // create and push back the FDE entry
+ EhFrame::FDE* fde = new EhFrame::FDE(pRegion,
+ pEhFrame.cie_back(),
+ pToken.data_off);
+ pEhFrame.addFDE(*fde);
+ return true;
+}
+
+bool EhFrameReader::addTerm(EhFrame& pEhFrame,
+ MemoryRegion& pRegion,
+ const EhFrameReader::Token& pToken)
+{
+ RegionFragment* frag = new RegionFragment(pRegion);
+ pEhFrame.addFragment(*frag);
+ return true;
+}
+
+bool EhFrameReader::reject(EhFrame& pEhFrame,
+ MemoryRegion& pRegion,
+ const EhFrameReader::Token& pToken)
+{
+ return true;
+}
+
diff --git a/lib/LD/FDE.cpp b/lib/LD/FDE.cpp
deleted file mode 100644
index 1aa196b..0000000
--- a/lib/LD/FDE.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//===- FDE.cpp ------------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <mcld/LD/FDE.h>
-#include <mcld/LD/EhFrame.h>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// FDE
-//===----------------------------------------------------------------------===//
-FDE::FDE(MemoryRegion& pRegion, const CIE& pCIE, Offset pPCBeginOffset)
- : RegionFragment(pRegion), m_CIE(pCIE), m_PCBeginOffset(pPCBeginOffset) {
-}
-
-FDE::~FDE()
-{
-}
diff --git a/lib/LD/FragmentRef.cpp b/lib/LD/FragmentRef.cpp
deleted file mode 100644
index 9ae8e4d..0000000
--- a/lib/LD/FragmentRef.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-//===- FragmentRef.cpp --------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <mcld/LD/FragmentRef.h>
-
-#include <cstring>
-#include <cassert>
-
-#include <llvm/Support/MathExtras.h>
-#include <llvm/Support/Casting.h>
-
-#include <mcld/LD/AlignFragment.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/RegionFragment.h>
-#include <mcld/LD/TargetFragment.h>
-#include <mcld/LD/Layout.h>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// Helper Functions
-//===----------------------------------------------------------------------===//
-/// compunteFragmentSize - compute the specific Fragment size
-uint64_t mcld::computeFragmentSize(const Layout& pLayout,
- const Fragment& pFrag)
-{
- switch (pFrag.getKind()) {
- case Fragment::Fillment:
- return static_cast<const FillFragment&>(pFrag).getSize();
-
- case Fragment::Alignment: {
- uint64_t offset = pLayout.getOutputOffset(pFrag);
- const AlignFragment& align_frag = llvm::cast<AlignFragment>(pFrag);
- uint64_t size = llvm::OffsetToAlignment(offset, align_frag.getAlignment());
- if (size > align_frag.getMaxBytesToEmit())
- return 0;
- return size;
- }
-
- case Fragment::Region:
- return llvm::cast<RegionFragment>(pFrag).getRegion().size();
-
- case Fragment::Target:
- return llvm::cast<TargetFragment>(pFrag).getSize();
-
- case Fragment::Relocation:
- assert(0 && "the size of FT_Reloc fragment is handled by backend");
- return 0;
-
- default:
- assert(0 && "invalid fragment kind");
- return 0;
- }
-}
-
-//===----------------------------------------------------------------------===//
-// FragmentRef
-//===----------------------------------------------------------------------===//
-FragmentRef::FragmentRef()
- : m_pFragment(NULL), m_Offset(0) {
-}
-
-FragmentRef::FragmentRef(Fragment& pFrag,
- FragmentRef::Offset pOffset)
- : m_pFragment(&pFrag), m_Offset(pOffset) {
-}
-
-FragmentRef::~FragmentRef()
-{
- m_pFragment = NULL;
- m_Offset = 0;
-}
-
-FragmentRef& FragmentRef::assign(const FragmentRef& pCopy)
-{
- m_pFragment = const_cast<Fragment*>(pCopy.m_pFragment);
- m_Offset = pCopy.m_Offset;
- return *this;
-}
-
-FragmentRef& FragmentRef::assign(Fragment& pFrag, FragmentRef::Offset pOffset)
-{
- m_pFragment = &pFrag;
- m_Offset = pOffset;
- return *this;
-}
-
-void FragmentRef::memcpy(void* pDest, size_t pNBytes, Offset pOffset) const
-{
- // check if the offset is still in a legal range.
- if (NULL == m_pFragment)
- return;
- unsigned int total_offset = m_Offset + pOffset;
- switch(m_pFragment->getKind()) {
- case Fragment::Region: {
- RegionFragment* region_frag = static_cast<RegionFragment*>(m_pFragment);
- unsigned int total_length = region_frag->getRegion().size();
- if (total_length < (total_offset+pNBytes))
- pNBytes = total_length - total_offset;
-
- std::memcpy(pDest, region_frag->getRegion().getBuffer(total_offset), pNBytes);
- return;
- }
- case Fragment::Alignment:
- case Fragment::Fillment:
- default:
- return;
- }
-}
-
-FragmentRef::Address FragmentRef::deref()
-{
- if (NULL == m_pFragment)
- return NULL;
- Address base = NULL;
- switch(m_pFragment->getKind()) {
- case Fragment::Region:
- base = static_cast<RegionFragment*>(m_pFragment)->getRegion().getBuffer();
- break;
- case Fragment::Alignment:
- case Fragment::Fillment:
- default:
- return NULL;
- }
- return base + m_Offset;
-}
-
-FragmentRef::ConstAddress FragmentRef::deref() const
-{
- if (NULL == m_pFragment)
- return NULL;
- ConstAddress base = NULL;
- switch(m_pFragment->getKind()) {
- case Fragment::Region:
- base = static_cast<const RegionFragment*>(m_pFragment)->getRegion().getBuffer();
- break;
- case Fragment::Alignment:
- case Fragment::Fillment:
- default:
- return NULL;
- }
- return base + m_Offset;
-}
-
diff --git a/lib/LD/GNUArchiveReader.cpp b/lib/LD/GNUArchiveReader.cpp
index 55c8c76..9aeaa6b 100644
--- a/lib/LD/GNUArchiveReader.cpp
+++ b/lib/LD/GNUArchiveReader.cpp
@@ -6,17 +6,18 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/InputTree.h>
#include <mcld/LD/GNUArchiveReader.h>
+
+#include <mcld/Module.h>
+#include <mcld/InputTree.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/MC/MCLDInput.h>
#include <mcld/LD/ResolveInfo.h>
#include <mcld/LD/ELFObjectReader.h>
#include <mcld/Support/FileSystem.h>
#include <mcld/Support/FileHandle.h>
#include <mcld/Support/MemoryArea.h>
#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/MemoryAreaFactory.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Support/Path.h>
#include <mcld/ADT/SizeTraits.h>
@@ -29,11 +30,9 @@
using namespace mcld;
-GNUArchiveReader::GNUArchiveReader(MCLDInfo& pLDInfo,
- MemoryAreaFactory& pMemAreaFactory,
+GNUArchiveReader::GNUArchiveReader(Module& pModule,
ELFObjectReader& pELFObjectReader)
- : m_LDInfo(pLDInfo),
- m_MemAreaFactory(pMemAreaFactory),
+ : m_Module(pModule),
m_ELFObjectReader(pELFObjectReader)
{
}
@@ -90,6 +89,11 @@
bool GNUArchiveReader::readArchive(Archive& pArchive)
{
+ if (pArchive.getARFile().attribute()->isWholeArchive())
+ return includeAllMembers(pArchive);
+
+ // if this is the first time read this archive, setup symtab and strtab
+ if (pArchive.getSymbolTable().empty()) {
// read the symtab of the archive
readSymbolTable(pArchive);
@@ -100,6 +104,7 @@
pArchive.addArchiveMember(pArchive.getARFile().name(),
pArchive.inputs().root(),
&InputTree::Downward);
+ }
// include the needed members in the archive and build up the input tree
bool willSymResolved;
@@ -123,56 +128,8 @@
pArchive.setSymbolStatus(idx, status);
if (Archive::Symbol::Include == status) {
- Input* cur_archive = &(pArchive.getARFile());
- Input* member = cur_archive;
- uint32_t file_offset = pArchive.getObjFileOffset(idx);
- while ((member != NULL) && (Input::Object != member->type())) {
- uint32_t nested_offset = 0;
- // use the file offset in current archive to find out the member we
- // want to include
- member = readMemberHeader(pArchive,
- *cur_archive,
- file_offset,
- nested_offset);
- assert(member != NULL);
- // bypass if we get an archive that is already in the map
- if (Input::Archive == member->type()) {
- cur_archive = member;
- file_offset = nested_offset;
- continue;
- }
-
- // insert a node into the subtree of current archive.
- Archive::ArchiveMember* parent =
- pArchive.getArchiveMember(cur_archive->name());
-
- assert(NULL != parent);
- pArchive.inputs().insert(parent->lastPos, *(parent->move), *member);
-
- // move the iterator to new created node, and also adjust the
- // direction to Afterward for next insertion in this subtree
- parent->move->move(parent->lastPos);
- parent->move = &InputTree::Afterward;
-
- if (m_ELFObjectReader.isMyFormat(*member)) {
- member->setType(Input::Object);
- pArchive.addObjectMember(pArchive.getObjFileOffset(idx),
- parent->lastPos);
- m_ELFObjectReader.readObject(*member);
- m_ELFObjectReader.readSections(*member);
- m_ELFObjectReader.readSymbols(*member);
- }
- else if (isMyFormat(*member)) {
- member->setType(Input::Archive);
- // when adding a new archive node, set the iterator to archive
- // itself, and set the direction to Downward
- pArchive.addArchiveMember(member->name(),
- parent->lastPos,
- &InputTree::Downward);
- cur_archive = member;
- file_offset = nested_offset;
- }
- } // end of while
+ // include the object member from the given offset
+ includeMember(pArchive, pArchive.getObjFileOffset(idx));
willSymResolved = true;
} // end of if
} // end of for
@@ -189,10 +146,12 @@
/// @param pArchiveFile - the archive that contains the needed object
/// @param pFileOffset - file offset of the member header in the archive
/// @param pNestedOffset - used when we find a nested archive
+/// @param pMemberSize - the file size of this member
Input* GNUArchiveReader::readMemberHeader(Archive& pArchiveRoot,
Input& pArchiveFile,
uint32_t pFileOffset,
- uint32_t& pNestedOffset)
+ uint32_t& pNestedOffset,
+ size_t& pMemberSize)
{
assert(pArchiveFile.hasMemArea());
@@ -202,13 +161,13 @@
const Archive::MemberHeader* header =
reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
- assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2));
+ assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, sizeof(header->fmag)));
- // int size = atoi(header->size);
+ pMemberSize = atoi(header->size);
// parse the member name and nested offset if any
std::string member_name;
- llvm::StringRef name_field(header->name, 16);
+ llvm::StringRef name_field(header->name, sizeof(header->name));
if ('/' != header->name[0]) {
// this is an object file in an archive
size_t pos = name_field.find_first_of('/');
@@ -230,24 +189,22 @@
}
// get the member name from the extended name table
+ assert(pArchiveRoot.hasStrTable());
begin = name_offset;
end = pArchiveRoot.getStrTable().find_first_of('\n', begin);
member_name.assign(pArchiveRoot.getStrTable().substr(begin, end - begin -1));
}
Input* member = NULL;
- if (!isThinArchive(pArchiveFile)) {
+ bool isThinAR = isThinArchive(pArchiveFile);
+ if (!isThinAR) {
// this is an object file in an archive
- member =
- m_LDInfo.inputFactory().produce(member_name,
- pArchiveFile.path(),
- Input::Unknown,
- (pFileOffset +
- sizeof(Archive::MemberHeader)));
- assert(member != NULL);
- member->setMemArea(pArchiveFile.memArea());
- LDContext *input_context = m_LDInfo.contextFactory().produce();
- member->setContext(input_context);
+ member = pArchiveRoot.getMemberFile(pArchiveFile,
+ isThinAR,
+ member_name,
+ pArchiveFile.path(),
+ (pFileOffset +
+ sizeof(Archive::MemberHeader)));
}
else {
// this is a member in a thin archive
@@ -265,21 +222,11 @@
input_path.append(member_name);
else
input_path.assign(member_name);
- member =
- m_LDInfo.inputFactory().produce(member_name, input_path, Input::Unknown);
- assert(member != NULL);
- MemoryArea* input_memory =
- m_MemAreaFactory.produce(member->path(), FileHandle::ReadOnly);
- if (input_memory->handler()->isGood()) {
- member->setMemArea(input_memory);
- }
- else {
- error(diag::err_cannot_open_input) << member->name() << member->path();
- return NULL;
- }
- LDContext *input_context = m_LDInfo.contextFactory().produce(input_path);
- member->setContext(input_context);
+ member = pArchiveRoot.getMemberFile(pArchiveFile,
+ isThinAR,
+ member_name,
+ input_path);
}
pArchiveFile.memArea()->release(header_region);
@@ -297,42 +244,44 @@
sizeof(Archive::MemberHeader));
const Archive::MemberHeader* header =
reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
- assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2));
+ assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, sizeof(header->fmag)));
int symtab_size = atoi(header->size);
pArchive.setSymTabSize(symtab_size);
- MemoryRegion* symtab_region =
- pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() +
+ if (!pArchive.getARFile().attribute()->isWholeArchive()) {
+ MemoryRegion* symtab_region =
+ pArchive.getARFile().memArea()->request(
+ (pArchive.getARFile().fileOffset() +
Archive::MAGIC_LEN +
sizeof(Archive::MemberHeader)),
symtab_size);
- const uint32_t* data =
- reinterpret_cast<const uint32_t*>(symtab_region->getBuffer());
+ const uint32_t* data =
+ reinterpret_cast<const uint32_t*>(symtab_region->getBuffer());
- // read the number of symbols
- uint32_t number = 0;
- if (llvm::sys::isLittleEndianHost())
- number = bswap32(*data);
- else
- number = *data;
-
- // set up the pointers for file offset and name offset
- ++data;
- const char* name = reinterpret_cast<const char*>(data + number);
-
- // add the archive symbols
- for (uint32_t i = 0; i < number; ++i) {
+ // read the number of symbols
+ uint32_t number = 0;
if (llvm::sys::isLittleEndianHost())
- pArchive.addSymbol(name, bswap32(*data));
+ number = bswap32(*data);
else
- pArchive.addSymbol(name, *data);
- name += strlen(name) + 1;
- ++data;
- }
+ number = *data;
+ // set up the pointers for file offset and name offset
+ ++data;
+ const char* name = reinterpret_cast<const char*>(data + number);
+
+ // add the archive symbols
+ for (uint32_t i = 0; i < number; ++i) {
+ if (llvm::sys::isLittleEndianHost())
+ pArchive.addSymbol(name, bswap32(*data));
+ else
+ pArchive.addSymbol(name, *data);
+ name += strlen(name) + 1;
+ ++data;
+ }
+ pArchive.getARFile().memArea()->release(symtab_region);
+ }
pArchive.getARFile().memArea()->release(header_region);
- pArchive.getARFile().memArea()->release(symtab_region);
return true;
}
@@ -355,22 +304,22 @@
const Archive::MemberHeader* header =
reinterpret_cast<const Archive::MemberHeader*>(header_region->getBuffer());
- assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, 2));
+ assert(0 == memcmp(header->fmag, Archive::MEMBER_MAGIC, sizeof(header->fmag)));
- int strtab_size = atoi(header->size);
-
- MemoryRegion* strtab_region =
- pArchive.getARFile().memArea()->request((pArchive.getARFile().fileOffset() +
- offset +
- sizeof(Archive::MemberHeader)),
- strtab_size);
- const char* strtab =
- reinterpret_cast<const char*>(strtab_region->getBuffer());
-
- pArchive.getStrTable().assign(strtab, strtab_size);
-
+ if (0 == memcmp(header->name, Archive::STRTAB_NAME, sizeof(header->name))) {
+ // read the extended name table
+ int strtab_size = atoi(header->size);
+ MemoryRegion* strtab_region =
+ pArchive.getARFile().memArea()->request(
+ (pArchive.getARFile().fileOffset() +
+ offset + sizeof(Archive::MemberHeader)),
+ strtab_size);
+ const char* strtab =
+ reinterpret_cast<const char*>(strtab_region->getBuffer());
+ pArchive.getStrTable().assign(strtab, strtab_size);
+ pArchive.getARFile().memArea()->release(strtab_region);
+ }
pArchive.getARFile().memArea()->release(header_region);
- pArchive.getARFile().memArea()->release(strtab_region);
return true;
}
@@ -380,7 +329,7 @@
GNUArchiveReader::shouldIncludeSymbol(const llvm::StringRef& pSymName) const
{
// TODO: handle symbol version issue and user defined symbols
- ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pSymName);
+ const ResolveInfo* info = m_Module.getNamePool().findInfo(pSymName);
if (NULL != info) {
if (!info->isUndef())
return Archive::Symbol::Exclude;
@@ -391,3 +340,107 @@
return Archive::Symbol::Unknown;
}
+/// includeMember - include the object member in the given file offset, and
+/// return the size of the object
+/// @param pArchiveRoot - the archive root
+/// @param pFileOffset - file offset of the member header in the archive
+size_t GNUArchiveReader::includeMember(Archive& pArchive, uint32_t pFileOffset)
+{
+ Input* cur_archive = &(pArchive.getARFile());
+ Input* member = NULL;
+ uint32_t file_offset = pFileOffset;
+ size_t size = 0;
+ do {
+ uint32_t nested_offset = 0;
+ // use the file offset in current archive to find out the member we
+ // want to include
+ member = readMemberHeader(pArchive,
+ *cur_archive,
+ file_offset,
+ nested_offset,
+ size);
+ assert(member != NULL);
+ // bypass if we get an archive that is already in the map
+ if (Input::Archive == member->type()) {
+ cur_archive = member;
+ file_offset = nested_offset;
+ continue;
+ }
+
+ // insert a node into the subtree of current archive.
+ Archive::ArchiveMember* parent =
+ pArchive.getArchiveMember(cur_archive->name());
+
+ assert(NULL != parent);
+ pArchive.inputs().insert(parent->lastPos, *(parent->move), *member);
+
+ // move the iterator to new created node, and also adjust the
+ // direction to Afterward for next insertion in this subtree
+ parent->move->move(parent->lastPos);
+ parent->move = &InputTree::Afterward;
+
+ if (m_ELFObjectReader.isMyFormat(*member)) {
+ member->setType(Input::Object);
+ pArchive.addObjectMember(pFileOffset, parent->lastPos);
+ m_ELFObjectReader.readHeader(*member);
+ m_ELFObjectReader.readSections(*member);
+ m_ELFObjectReader.readSymbols(*member);
+ m_Module.getObjectList().push_back(member);
+ }
+ else if (isMyFormat(*member)) {
+ member->setType(Input::Archive);
+ // when adding a new archive node, set the iterator to archive
+ // itself, and set the direction to Downward
+ pArchive.addArchiveMember(member->name(),
+ parent->lastPos,
+ &InputTree::Downward);
+ cur_archive = member;
+ file_offset = nested_offset;
+ }
+ } while (Input::Object != member->type());
+ return size;
+}
+
+/// includeAllMembers - include all object members. This is called if
+/// --whole-archive is the attribute for this archive file.
+bool GNUArchiveReader::includeAllMembers(Archive& pArchive)
+{
+ // read the symtab of the archive
+ readSymbolTable(pArchive);
+
+ // read the strtab of the archive
+ readStringTable(pArchive);
+
+ // add root archive to ArchiveMemberMap
+ pArchive.addArchiveMember(pArchive.getARFile().name(),
+ pArchive.inputs().root(),
+ &InputTree::Downward);
+
+ bool isThinAR = isThinArchive(pArchive.getARFile());
+ uint32_t begin_offset = pArchive.getARFile().fileOffset() +
+ Archive::MAGIC_LEN +
+ sizeof(Archive::MemberHeader) +
+ pArchive.getSymTabSize();
+ if (pArchive.hasStrTable()) {
+ if (0x0 != (begin_offset & 1))
+ ++begin_offset;
+ begin_offset += sizeof(Archive::MemberHeader) +
+ pArchive.getStrTable().size();
+ }
+ uint32_t end_offset = pArchive.getARFile().memArea()->handler()->size();
+ for (uint32_t offset = begin_offset;
+ offset < end_offset;
+ offset += sizeof(Archive::MemberHeader)) {
+
+ size_t size = includeMember(pArchive, offset);
+
+ if (!isThinAR) {
+ offset += size;
+ }
+
+ if (0x0 != (offset & 1))
+ ++offset;
+ }
+ return true;
+}
+
diff --git a/lib/LD/GroupReader.cpp b/lib/LD/GroupReader.cpp
new file mode 100644
index 0000000..91e79c0
--- /dev/null
+++ b/lib/LD/GroupReader.cpp
@@ -0,0 +1,138 @@
+//===- GroupReader.cpp ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/Archive.h>
+#include <mcld/LD/ArchiveReader.h>
+#include <mcld/LD/DynObjReader.h>
+#include <mcld/LD/GroupReader.h>
+#include <mcld/LD/ObjectReader.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/Support/MsgHandling.h>
+
+using namespace mcld;
+
+GroupReader::GroupReader(Module& pModule,
+ ObjectReader& pObjectReader,
+ DynObjReader& pDynObjReader,
+ ArchiveReader& pArchiveReader)
+ : m_Module(pModule),
+ m_ObjectReader(pObjectReader),
+ m_DynObjReader(pDynObjReader),
+ m_ArchiveReader(pArchiveReader)
+{
+}
+
+GroupReader::~GroupReader()
+{
+}
+
+bool GroupReader::readGroup(Module::input_iterator pRoot,
+ InputBuilder& pBuilder,
+ const LinkerConfig& pConfig)
+{
+ // record the number of total objects included in this sub-tree
+ size_t cur_obj_cnt = 0;
+ size_t last_obj_cnt = 0;
+ size_t non_ar_obj_cnt = 0;
+
+ // record the archive files in this sub-tree
+ typedef std::vector<ArchiveListEntry*> ArchiveListType;
+ ArchiveListType ar_list;
+
+ Module::input_iterator input = --pRoot;
+
+ // Since the end of a sub-tree is the same node to the end of whole tree, we
+ // take the end of the whole input tree for conventience.
+ Module::input_iterator input_end = m_Module.input_end();
+
+ // first time read the sub-tree
+ while (input != input_end) {
+ // already got type - for example, bitcode or external OIR (object
+ // intermediate representation)
+ if ((*input)->type() == Input::Script ||
+ (*input)->type() == Input::Object ||
+ (*input)->type() == Input::DynObj ||
+ (*input)->type() == Input::Archive ||
+ (*input)->type() == Input::External) {
+ ++input;
+ continue;
+ }
+
+ // is an archive
+ if (m_ArchiveReader.isMyFormat(**input)) {
+ (*input)->setType(Input::Archive);
+ // record the Archive used by each archive node
+ Archive* ar = new Archive(**input, pBuilder);
+ ArchiveListEntry* entry = new ArchiveListEntry(*ar, input);
+ ar_list.push_back(entry);
+ // read archive
+ m_ArchiveReader.readArchive(*ar);
+ cur_obj_cnt += ar->numOfObjectMember();
+ }
+ // is a relocatable object file
+ else if (m_ObjectReader.isMyFormat(**input)) {
+ (*input)->setType(Input::Object);
+ m_ObjectReader.readHeader(**input);
+ m_ObjectReader.readSections(**input);
+ m_ObjectReader.readSymbols(**input);
+ m_Module.getObjectList().push_back(*input);
+ ++cur_obj_cnt;
+ ++non_ar_obj_cnt;
+ }
+ // is a shared object file
+ else if (m_DynObjReader.isMyFormat(**input)) {
+ (*input)->setType(Input::DynObj);
+ m_DynObjReader.readHeader(**input);
+ m_DynObjReader.readSymbols(**input);
+ m_Module.getLibraryList().push_back(*input);
+ }
+ else {
+ fatal(diag::err_unrecognized_input_file) << (*input)->path()
+ << pConfig.triple().str();
+ }
+ ++input;
+ }
+
+ // after read in all the archives, traverse the archive list in a loop until
+ // there is no unresolved symbols added
+ ArchiveListType::iterator it = ar_list.begin();
+ ArchiveListType::iterator end = ar_list.end();
+ while (cur_obj_cnt != last_obj_cnt) {
+ last_obj_cnt = cur_obj_cnt;
+ cur_obj_cnt = non_ar_obj_cnt;
+ for (it = ar_list.begin(); it != end; ++it) {
+ Archive& ar = (*it)->archive;
+ // if --whole-archive is given to this archive, no need to read it again
+ if ( ar.getARFile().attribute()->isWholeArchive())
+ continue;
+ m_ArchiveReader.readArchive(ar);
+ cur_obj_cnt += ar.numOfObjectMember();
+ }
+ }
+
+ // after all needed member included, merge the archive sub-tree to main
+ // InputTree
+ for (it = ar_list.begin(); it != end; ++it) {
+ Archive& ar = (*it)->archive;
+ if (ar.numOfObjectMember() > 0) {
+ m_Module.getInputTree().merge<InputTree::Inclusive>((*it)->input,
+ ar.inputs());
+ }
+ }
+
+ // cleanup ar_list
+ for (it = ar_list.begin(); it != end; ++it) {
+ delete &((*it)->archive);
+ delete (*it);
+ }
+ ar_list.clear();
+
+ return true;
+}
+
diff --git a/lib/LD/LDContext.cpp b/lib/LD/LDContext.cpp
index f6556f3..8607dfd 100644
--- a/lib/LD/LDContext.cpp
+++ b/lib/LD/LDContext.cpp
@@ -13,14 +13,16 @@
using namespace mcld;
-//==========================
-// LDReader
-LDContext::LDContext()
+//===----------------------------------------------------------------------===//
+// LDContext
+//===----------------------------------------------------------------------===//
+LDContext& LDContext::appendSection(LDSection& pSection)
{
-}
-
-LDContext::~LDContext()
-{
+ if (LDFileFormat::Relocation == pSection.kind())
+ m_RelocSections.push_back(&pSection);
+ pSection.setIndex(m_SectionTable.size());
+ m_SectionTable.push_back(&pSection);
+ return *this;
}
LDSection* LDContext::getSection(unsigned int pIdx)
diff --git a/lib/LD/LDFileFormat.cpp b/lib/LD/LDFileFormat.cpp
index c1ddb52..bb878b8 100644
--- a/lib/LD/LDFileFormat.cpp
+++ b/lib/LD/LDFileFormat.cpp
@@ -7,12 +7,13 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/LD/LDFileFormat.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/Fragment/FragmentLinker.h>
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// LDFileInfo
+//===----------------------------------------------------------------------===//
LDFileFormat::LDFileFormat()
: f_pTextSection(NULL),
f_pDataSection(NULL),
@@ -24,9 +25,3 @@
{
}
-void LDFileFormat::initStdSections(MCLinker& pLinker)
-{
- initObjectFormat(pLinker);
- initObjectType(pLinker);
-}
-
diff --git a/lib/LD/LDSection.cpp b/lib/LD/LDSection.cpp
index 2aad917..30daee3 100644
--- a/lib/LD/LDSection.cpp
+++ b/lib/LD/LDSection.cpp
@@ -8,26 +8,102 @@
//===----------------------------------------------------------------------===//
#include <mcld/LD/LDSection.h>
+#include <mcld/Support/GCFactory.h>
+
+#include <llvm/Support/ManagedStatic.h>
+
using namespace mcld;
+typedef GCFactory<LDSection, MCLD_SECTIONS_PER_INPUT> SectionFactory;
+
+static llvm::ManagedStatic<SectionFactory> g_SectFactory;
+
+//===----------------------------------------------------------------------===//
+// LDSection
+//===----------------------------------------------------------------------===//
+LDSection::LDSection()
+ : m_Name(),
+ m_Kind(LDFileFormat::Ignore),
+ m_Type(0x0),
+ m_Flag(0x0),
+ m_Size(0),
+ m_Offset(~uint64_t(0)),
+ m_Addr(0x0),
+ m_Align(0),
+ m_Info(0),
+ m_pLink(NULL),
+ m_Index(0) {
+ m_Data.sect_data = NULL;
+}
+
LDSection::LDSection(const std::string& pName,
LDFileFormat::Kind pKind,
uint32_t pType,
uint32_t pFlag,
uint64_t pSize,
- uint64_t pOffset,
uint64_t pAddr)
: m_Name(pName),
m_Kind(pKind),
m_Type(pType),
m_Flag(pFlag),
m_Size(pSize),
- m_Offset(pOffset),
+ m_Offset(~uint64_t(0)),
m_Addr(pAddr),
m_Align(0),
m_Info(0),
m_pLink(NULL),
- m_pSectionData(NULL),
m_Index(0) {
+ m_Data.sect_data = NULL;
+}
+
+LDSection::~LDSection()
+{
+}
+
+bool LDSection::hasOffset() const
+{
+ return (m_Offset != ~uint64_t(0));
+}
+
+LDSection* LDSection::Create(const std::string& pName,
+ LDFileFormat::Kind pKind,
+ uint32_t pType,
+ uint32_t pFlag,
+ uint64_t pSize,
+ uint64_t pAddr)
+{
+ LDSection* result = g_SectFactory->allocate();
+ new (result) LDSection(pName, pKind, pType, pFlag, pSize, pAddr);
+ return result;
+}
+
+void LDSection::Destroy(LDSection*& pSection)
+{
+ g_SectFactory->destroy(pSection);
+ g_SectFactory->deallocate(pSection);
+ pSection = NULL;
+}
+
+void LDSection::Clear()
+{
+ g_SectFactory->clear();
+}
+
+bool LDSection::hasSectionData() const
+{
+ assert(LDFileFormat::Relocation != kind() && LDFileFormat::EhFrame != kind());
+ return (NULL != m_Data.sect_data);
+}
+
+bool LDSection::hasRelocData() const
+{
+ assert(LDFileFormat::Relocation == kind());
+ return (NULL != m_Data.reloc_data);
+}
+
+bool LDSection::hasEhFrame() const
+{
+ assert(LDFileFormat::EhFrame == kind());
+ return (NULL != m_Data.eh_frame);
}
diff --git a/lib/LD/LDSectionFactory.cpp b/lib/LD/LDSectionFactory.cpp
deleted file mode 100644
index a81c839..0000000
--- a/lib/LD/LDSectionFactory.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-//===- LDSectionFactory.cpp -----------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/LD/LDSectionFactory.h>
-
-using namespace mcld;
-
-//==========================
-// LDSectionFactory
-LDSectionFactory::LDSectionFactory(size_t pNum)
- : GCFactory<LDSection, 0>(pNum) {
-}
-
-LDSectionFactory::~LDSectionFactory()
-{
-}
-
-LDSection* LDSectionFactory::produce(const std::string& pName,
- LDFileFormat::Kind pKind,
- uint32_t pType,
- uint32_t pFlag)
-{
- // create a LDSection
- LDSection* result = allocate();
- new (result) LDSection(pName, pKind, pType, pFlag);
- return result;
-}
-
-void LDSectionFactory::destroy(LDSection*& pSection)
-{
- // do not recycle LDSection. HeaderFactory will do that job.
- deallocate(pSection);
-}
-
-LDSection* LDSectionFactory::find(const std::string& pName)
-{
- iterator sect_iter, sect_end = end();
- for (sect_iter = begin(); sect_iter != sect_end; ++sect_iter)
- if ((*sect_iter).name() == pName)
- break;
- if (sect_iter == sect_end)
- return NULL;
- return &(*sect_iter);
-}
diff --git a/lib/LD/LDSymbol.cpp b/lib/LD/LDSymbol.cpp
index f088b5c..c6fab43 100644
--- a/lib/LD/LDSymbol.cpp
+++ b/lib/LD/LDSymbol.cpp
@@ -6,13 +6,28 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#include <mcld/LD/LDSymbol.h>
+#include <mcld/Config/Config.h>
+#include <mcld/Fragment/FragmentRef.h>
+#include <mcld/Fragment/NullFragment.h>
+#include <mcld/Support/GCFactory.h>
+
#include <cstring>
+#include <llvm/Support/ManagedStatic.h>
+
using namespace mcld;
+static LDSymbol* g_NullSymbol = NULL;
+
+typedef GCFactory<LDSymbol, MCLD_SYMBOLS_PER_INPUT> LDSymbolFactory;
+
+static llvm::ManagedStatic<LDSymbolFactory> g_LDSymbolFactory;
+
+//===----------------------------------------------------------------------===//
+// LDSymbol
+//===----------------------------------------------------------------------===//
LDSymbol::LDSymbol()
: m_pResolveInfo(NULL), m_pFragRef(NULL), m_Value(0) {
}
@@ -35,6 +50,38 @@
return (*this);
}
+LDSymbol* LDSymbol::Create(ResolveInfo& pResolveInfo)
+{
+ LDSymbol* result = g_LDSymbolFactory->allocate();
+ new (result) LDSymbol();
+ result->setResolveInfo(pResolveInfo);
+ return result;
+}
+
+void LDSymbol::Destroy(LDSymbol*& pSymbol)
+{
+ pSymbol->~LDSymbol();
+ g_LDSymbolFactory->deallocate(pSymbol);
+ pSymbol = NULL;
+}
+
+void LDSymbol::Clear()
+{
+ g_LDSymbolFactory->clear();
+}
+
+LDSymbol* LDSymbol::Null()
+{
+ if (NULL == g_NullSymbol) {
+ g_NullSymbol = new LDSymbol();
+ g_NullSymbol->setResolveInfo(*ResolveInfo::Null());
+ NullFragment* null_frag = new NullFragment();
+ g_NullSymbol->setFragmentRef(FragmentRef::Create(*null_frag, 0));
+ ResolveInfo::Null()->setSymPtr(g_NullSymbol);
+ }
+ return g_NullSymbol;
+}
+
void LDSymbol::setFragmentRef(FragmentRef* pFragmentRef)
{
m_pFragRef = pFragmentRef;
@@ -45,3 +92,13 @@
m_pResolveInfo = const_cast<ResolveInfo*>(&pInfo);
}
+bool LDSymbol::isNull() const
+{
+ return (this == Null());
+}
+
+bool LDSymbol::hasFragRef() const
+{
+ return !m_pFragRef->isNull();
+}
+
diff --git a/lib/LD/Layout.cpp b/lib/LD/Layout.cpp
index 1650556..a2a1028 100644
--- a/lib/LD/Layout.cpp
+++ b/lib/LD/Layout.cpp
@@ -6,524 +6,35 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#include <mcld/LD/Layout.h>
-#include <cassert>
-
-#include <llvm/ADT/Twine.h>
-
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/ADT/SizeTraits.h>
-#include <mcld/LD/LDContext.h>
#include <mcld/LD/LDFileFormat.h>
#include <mcld/LD/LDSection.h>
-#include <mcld/LD/Fragment.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/AlignFragment.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/MC/MCLDInfo.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Target/TargetLDBackend.h>
using namespace mcld;
//===----------------------------------------------------------------------===//
-// Range
-//===----------------------------------------------------------------------===//
-Layout::Range::Range()
- : header(NULL),
- prevRear(NULL) {
-}
-
-Layout::Range::Range(const LDSection& pHdr)
- : header(const_cast<LDSection*>(&pHdr)),
- prevRear(NULL) {
-}
-
-Layout::Range::~Range()
-{
-}
-
-//===----------------------------------------------------------------------===//
// Layout
//===----------------------------------------------------------------------===//
-Layout::Layout()
- : m_FragRefFactory(32) /** magic number **/ {
-}
-
-Layout::~Layout()
-{
-}
-
-void Layout::setFragmentLayoutOrder(Fragment* pFrag)
-{
- if (NULL == pFrag)
- return;
-
- /// find the most-recent fragment whose order was set.
- Fragment* first = pFrag;
- while (!hasLayoutOrder(*first)) {
- if (NULL == first->getPrevNode())
- break;
- first = first->getPrevNode();
- }
-
- /// set all layout order
-
- // find the first fragment who has no order.
- // find the last order of the fragment
- unsigned int layout_order = 0;
- Fragment* frag_not_set = NULL;
- if (NULL == first->getPrevNode()) {
- layout_order = 0;
- frag_not_set = first;
- }
- else {
- layout_order = first->getLayoutOrder();
- frag_not_set = first->getNextNode();
- }
-
- // for all fragments that has no order, set up its order
- while(NULL != frag_not_set) {
- frag_not_set->setLayoutOrder(layout_order);
- ++layout_order;
- frag_not_set = frag_not_set->getNextNode();
- }
-}
-
-/// setFragmentLayoutOffset - set the fragment's layout offset. This function
-/// also set up the layout offsets of all the fragments in the same range.
-/// If the offset of the fragment was set before, return immediately.
-void Layout::setFragmentLayoutOffset(Fragment* pFrag)
-{
- if (NULL == pFrag)
- return;
-
- // find the most-recent fragment whose offset was set.
- Fragment* first = pFrag;
-
- while (!hasLayoutOffset(*first)) {
- if (NULL == first->getPrevNode())
- break;
- first = first->getPrevNode();
- }
-
- // set all layout order
- uint64_t offset = 0;
- Fragment* frag_not_set = NULL;
- if (NULL == first->getPrevNode()) {
- offset = 0;
- frag_not_set = first;
- }
- else {
- offset = first->getOffset();
- offset += computeFragmentSize(*this, *first);
- frag_not_set = first->getNextNode();
- }
-
- while(NULL != frag_not_set) {
- frag_not_set->setOffset(offset);
- offset += computeFragmentSize(*this, *frag_not_set);
- frag_not_set = frag_not_set->getNextNode();
- }
-}
-
-/// addInputRange
-/// 1. add a new range <pInputHdr, previous rear fragment>
-/// 2. compute the layout order of all previous ranges.
-/// 2. compute the layout offset of all previous ranges.
-void Layout::addInputRange(const SectionData& pSD,
- const LDSection& pInputHdr)
-{
- RangeList* range_list = NULL;
-
- // get or create the range_list
- if (pSD.getFragmentList().empty() || 0 == m_SDRangeMap.count(&pSD)) {
- range_list = new RangeList();
- m_SDRangeMap[&pSD] = range_list;
- }
- else {
- range_list = m_SDRangeMap[&pSD];
- }
-
- // make a range and push it into the range list
- Range* range = new Range(pInputHdr);
- range_list->push_back(range);
-
- // set up previous rear of the range.
- // FIXME: in current design, we can not add a range before finishing adding
- // fragments in the previous range. If the limitation keeps, we can set
- // prevRear to the last fragment in the SectionData simply.
- //
- // if the pSD's fragment list is empty, the range.prevRear keeps NULL.
- if (!pSD.getFragmentList().empty()) {
- range->prevRear =
- const_cast<Fragment*>(&pSD.getFragmentList().back());
- }
-
- // compute the layout order of the previous range.
- if (!isFirstRange(*range)) {
- setFragmentLayoutOrder(range->prevRear);
- setFragmentLayoutOffset(range->prevRear);
- }
-}
-
-/// appendFragment - append the given Fragment to the given SectionData,
-/// and insert a MCAlignFragment to preserve the required align constraint if
-/// needed
-uint64_t Layout::appendFragment(Fragment& pFrag,
- SectionData& pSD,
- uint32_t pAlignConstraint)
-{
- // insert MCAlignFragment into SectionData first if needed
- AlignFragment* align_frag = NULL;
- if (pAlignConstraint > 1) {
- align_frag = new AlignFragment(pAlignConstraint, // alignment
- 0x0, // the filled value
- 1u, // the size of filled value
- pAlignConstraint - 1, // max bytes to emit
- &pSD);
- }
-
- // append the fragment to the SectionData
- pFrag.setParent(&pSD);
- pSD.getFragmentList().push_back(&pFrag);
-
- // update the alignment of associated output LDSection if needed
- LDSection* output_sect = getOutputLDSection(pFrag);
- assert(NULL != output_sect);
- if (pAlignConstraint > output_sect->align())
- output_sect->setAlign(pAlignConstraint);
-
- // compute the fragment order and offset
- setFragmentLayoutOrder(&pFrag);
- setFragmentLayoutOffset(&pFrag);
-
- if (NULL != align_frag)
- return pFrag.getOffset() - align_frag->getOffset() + computeFragmentSize(*this, pFrag);
- else
- return computeFragmentSize(*this, pFrag);
-}
-
-/// getInputLDSection - give a Fragment, return the corresponding input
-/// LDSection*
-LDSection*
-Layout::getInputLDSection(const Fragment& pFrag)
-{
- const SectionData* sect_data = pFrag.getParent();
- // check the SectionData
- if (NULL == sect_data) {
- llvm::report_fatal_error(llvm::Twine("the fragment does not belong to") +
- llvm::Twine(" any SectionData.\n"));
- }
-
- // check the SectionData's range list
- if (0 == m_SDRangeMap.count(sect_data)) {
- llvm::report_fatal_error(llvm::Twine("INTERNAL BACKEND ERROR: ") +
- llvm::Twine("the input's SectionData is not ") +
- llvm::Twine("registered in the Layout.\nPlease ") +
- llvm::Twine("use MCLinker::getOrCreateSectData() ") +
- llvm::Twine("to get input's SectionData.\n"));
- }
-
- RangeList* range_list = m_SDRangeMap[sect_data];
- // the fragment who has the layout order is not in the last range.
- if (hasLayoutOrder(pFrag)) {
- Range range = range_list->back();
- if (isFirstRange(range)) {
- return range.header;
- }
- while(range.prevRear->getLayoutOrder() > pFrag.getLayoutOrder()) {
- if (NULL != range.getPrevNode())
- range = *range.getPrevNode();
- else
- return NULL;
- }
- return range.header;
- }
- // the fragment who has no layout order should be in the last range
- else {
- if (range_list->empty())
- return NULL;
- return range_list->back().header;
- }
-}
-
-/// getInputLDSection - give a Fragment, return the corresponding input
-/// LDSection*
-const LDSection*
-Layout::getInputLDSection(const Fragment& pFrag) const
-{
- const SectionData* sect_data = pFrag.getParent();
- // check the SectionData
- if (NULL == sect_data) {
- llvm::report_fatal_error(llvm::Twine("the fragment does not belong to") +
- llvm::Twine(" any SectionData.\n"));
- }
-
- // check the SectionData's range list
- if (0 == m_SDRangeMap.count(sect_data)) {
- llvm::report_fatal_error(llvm::Twine("INTERNAL BACKEND ERROR: ") +
- llvm::Twine("the input's SectionData is not ") +
- llvm::Twine("registered in the Layout.\nPlease ") +
- llvm::Twine("use MCLinker::getOrCreateSectData() ") +
- llvm::Twine("to get input's SectionData.\n"));
- }
-
- SDRangeMap::const_iterator range_list_iter = m_SDRangeMap.find(sect_data);
- const RangeList* range_list = range_list_iter->second;
- // the fragment who has the layout order is not in the last range.
- if (hasLayoutOrder(pFrag)) {
- Range range = range_list->back();
- if (isFirstRange(range)) {
- return range.header;
- }
- while(range.prevRear->getLayoutOrder() > pFrag.getLayoutOrder()) {
- if (NULL != range.getPrevNode())
- range = *range.getPrevNode();
- else
- return NULL;
- }
- return range.header;
- }
- // the fragment who has no layout order should be in the last range
- else {
- if (range_list->empty())
- return NULL;
- return range_list->back().header;
- }
-}
-
-/// getOutputLDSection
-LDSection* Layout::getOutputLDSection(const Fragment& pFrag)
-{
- SectionData* sect_data = pFrag.getParent();
- if (NULL == sect_data)
- return NULL;
-
- return const_cast<LDSection*>(§_data->getSection());
-}
-
-/// getOutputLDSection
-const LDSection* Layout::getOutputLDSection(const Fragment& pFrag) const
-{
- const SectionData* sect_data = pFrag.getParent();
- if (NULL == sect_data)
- return NULL;
-
- return §_data->getSection();
-}
-
-/// getFragmentRef - assume the ragne exist, find the fragment reference
-FragmentRef* Layout::getFragmentRef(Layout::Range& pRange, uint64_t pOffset)
-{
- if (isEmptyRange(pRange))
- return NULL;
-
- Fragment* front = getFront(pRange);
- if (NULL == front)
- return NULL;
-
- Fragment* rear = getRear(pRange);
- if (NULL == rear)
- return NULL;
-
- return getFragmentRef(*front, *rear, pOffset);
-}
-
-// @param pFront is the first fragment in the range.
-// @param pRear is the last fragment in the range.
-// @pOffset is the offset started from pFront.
-FragmentRef*
-Layout::getFragmentRef(Fragment& pFront, Fragment& pRear, uint64_t pOffset)
-{
- Fragment* front = &pFront;
- Fragment* rear = &pRear;
-
- if (!hasLayoutOffset(*rear)) {
- // compute layout order, offset
- setFragmentLayoutOrder(rear);
- setFragmentLayoutOffset(rear);
- }
-
- // compute the offset from overall start fragment.
- uint64_t target_offset = pFront.getOffset() + pOffset;
-
- // from front to rear, find the offset which is as large as possible
- // but smaller than the target_offset.
- while (front != rear) {
- if (Fragment::Alignment == front->getKind()) {
- // alignment fragments were not counted in target_offset.
- // Count in the size of alignment fragmen in target_offset here.
- uint64_t align_size = 0x0;
- if (NULL == front->getNextNode()) {
- // If the alignment fragment is the last fragment, increase
- // the target_offset by the alignment fragment's size.
- align_size = computeFragmentSize(*this, *front);
- }
- else {
- // If the alignment fragment is not the last fragment, the alignment
- // fragment's size is the distance between the two fragment.
- align_size = front->getNextNode()->getOffset() - front->getOffset();
- }
- target_offset += align_size;
- front = front->getNextNode();
- continue;
- }
-
- if (target_offset >= front->getNextNode()->getOffset()) {
- front = front->getNextNode();
- }
- else {
- // found
- FragmentRef* result = m_FragRefFactory.allocate();
- new (result) FragmentRef(*front, target_offset - front->getOffset());
- return result;
- }
- }
-
- if (front == rear) {
- if (Fragment::Alignment == front->getKind())
- return NULL;
-
- if (!isValidOffset(*front, target_offset))
- return NULL;
-
- FragmentRef* result = m_FragRefFactory.allocate();
- new (result) FragmentRef(*front, target_offset - front->getOffset());
- return result;
- }
- return NULL;
-}
-
-/// getFragmentRef - give a LDSection in input file and an offset, return
-/// the fragment reference.
-FragmentRef*
-Layout::getFragmentRef(const LDSection& pInputSection, uint64_t pOffset)
-{
- // find out which SectionData covers the range of input section header
- const SectionData* sect_data = pInputSection.getSectionData();
-
- // check range list
- if (0 == m_SDRangeMap.count(sect_data))
- return NULL;
-
- if (sect_data->getFragmentList().empty())
- return NULL;
-
- RangeList* range_list = m_SDRangeMap[sect_data];
-
- // find out the specific part in SectionData range
- RangeList::iterator range, rangeEnd = range_list->end();
- for (range = range_list->begin(); range != rangeEnd; ++range) {
- // found the range
- if (&pInputSection == range->header) {
- break;
- }
- }
-
- // range not found
- if (range == rangeEnd) {
- fatal(diag::err_section_not_laid_out) << pInputSection.name();
- }
-
- return getFragmentRef(*range, pOffset);
-}
-
-/// getFragmentRef - give a fragment and a big offset, return the fragment
-/// reference in the section data.
-///
-/// @param pFrag - the given fragment
-/// @param pBigOffset - the offset, can be larger than the fragment, but can
-/// not larger than this input section.
-/// @return if found, return the fragment. Otherwise, return NULL.
-FragmentRef*
-Layout::getFragmentRef(const Fragment& pFrag, uint64_t pBigOffset)
-{
- if (!hasLayoutOffset(pFrag)) {
- // compute layout order, offset
- setFragmentLayoutOrder(const_cast<Fragment*>(&pFrag));
- setFragmentLayoutOffset(const_cast<Fragment*>(&pFrag));
- }
-
- // find out which SectionData covers the range of input section header
- const SectionData* sect_data = pFrag.getParent();
-
- // check range list
- if (0 == m_SDRangeMap.count(sect_data)) {
- llvm::report_fatal_error(llvm::Twine("SectionData has no") +
- llvm::Twine(" correponding range list.\n"));
- }
-
- if (sect_data->getFragmentList().empty())
- return NULL;
-
- RangeList* range_list = m_SDRangeMap[sect_data];
-
- // find out the specific part in SectionData range
- uint64_t target_offset = pBigOffset + pFrag.getOffset();
-
- RangeList::iterator range, rangeEnd = range_list->end();
- for (range = range_list->begin(); range != rangeEnd; ++range) {
- if (isEmptyRange(*range))
- continue;
- if (getRear(*range)->getOffset() >= target_offset) {
- break;
- }
- }
-
- // range not found
- if (range == rangeEnd) {
- llvm::report_fatal_error(llvm::Twine("the offset is too big that") +
- llvm::Twine(" never be in the range list.\n"));
- }
-
- return getFragmentRef(*range, pBigOffset);
-}
-
-uint64_t Layout::getOutputOffset(const Fragment& pFrag)
-{
- if (!hasLayoutOffset(pFrag)) {
- // compute layout order, offset
- setFragmentLayoutOrder(const_cast<Fragment*>(&pFrag));
- setFragmentLayoutOffset(const_cast<Fragment*>(&pFrag));
- }
- return pFrag.getOffset();
-}
-
-uint64_t Layout::getOutputOffset(const Fragment& pFrag) const
-{
- if (!hasLayoutOffset(pFrag)) {
- llvm::report_fatal_error(llvm::Twine("INTERNAL BACKEND ERROR: ") +
- llvm::Twine("the function ") +
- llvm::Twine(__func__) +
- llvm::Twine(" can not be used before layout().\n"));
- }
- return pFrag.getOffset();
-}
-
-uint64_t Layout::getOutputOffset(const FragmentRef& pFragRef)
-{
- return getOutputOffset(*(pFragRef.frag())) + pFragRef.offset();
-}
-
-uint64_t Layout::getOutputOffset(const FragmentRef& pFragRef) const
-{
- return getOutputOffset(*(pFragRef.frag())) + pFragRef.offset();
-}
-
-void Layout::sortSectionOrder(const Output& pOutput,
- const TargetLDBackend& pBackend,
- const MCLDInfo& pInfo)
+void Layout::sortSectionOrder(const TargetLDBackend& pBackend,
+ const LinkerConfig& pConfig)
{
typedef std::pair<LDSection*, unsigned int> SectOrder;
typedef std::vector<SectOrder > SectListTy;
SectListTy sect_list;
// get section order from backend
- for (size_t index = 0; index < m_SectionOrder.size(); ++index)
- sect_list.push_back(std::make_pair(
+ for (size_t index = 0; index < m_SectionOrder.size(); ++index) {
+ sect_list.push_back(
+ std::make_pair(
m_SectionOrder[index],
- pBackend.getSectionOrder(pOutput, *m_SectionOrder[index], pInfo)));
+ pBackend.getSectionOrder(*m_SectionOrder[index])
+ ));
+ }
// simple insertion sort should be fine for general cases such as so and exec
for (unsigned int i = 1; i < sect_list.size(); ++i) {
@@ -547,21 +58,24 @@
/// 1. finalize fragment offset
/// 2. compute section order
/// 3. finalize section offset
-bool Layout::layout(Output& pOutput,
+bool Layout::layout(Module& pModule,
const TargetLDBackend& pBackend,
- const MCLDInfo& pInfo)
+ const LinkerConfig& pConfig)
{
// determine what sections in output context will go into final output, and
// push the needed sections into m_SectionOrder for later processing
- assert(pOutput.hasContext());
- LDContext& output_context = *pOutput.context();
- LDContext::sect_iterator it, itEnd = output_context.sectEnd();
- for (it = output_context.sectBegin(); it != itEnd; ++it) {
+ Module::iterator it, itEnd = pModule.end();
+ for (it = pModule.begin(); it != itEnd; ++it) {
// calculate 1. all fragment offset, and 2. the section order
LDSection* sect = *it;
switch (sect->kind()) {
- // ignore if there is no SectionData for certain section kinds
+ // take NULL and StackNote directly
+ case LDFileFormat::Null:
+ case LDFileFormat::StackNote:
+ m_SectionOrder.push_back(sect);
+ break;
+ // ignore if section size is 0
case LDFileFormat::Regular:
case LDFileFormat::Target:
case LDFileFormat::MetaData:
@@ -569,31 +83,16 @@
case LDFileFormat::Debug:
case LDFileFormat::EhFrame:
case LDFileFormat::GCCExceptTable:
- if (0 != sect->size()) {
- if (NULL != sect->getSectionData() &&
- !sect->getSectionData()->getFragmentList().empty()) {
- // make sure that all fragments are valid
- Fragment& frag = sect->getSectionData()->getFragmentList().back();
- setFragmentLayoutOrder(&frag);
- setFragmentLayoutOffset(&frag);
- }
- m_SectionOrder.push_back(sect);
- }
- break;
- // take NULL directly
- case LDFileFormat::Null:
- m_SectionOrder.push_back(sect);
- break;
- // ignore if section size is 0
case LDFileFormat::NamePool:
case LDFileFormat::Relocation:
case LDFileFormat::Note:
case LDFileFormat::EhFrameHdr:
- if (0 != sect->size())
+ if (0 != sect->size()) {
m_SectionOrder.push_back(sect);
+ }
break;
case LDFileFormat::Group:
- if (MCLDFile::Object == pOutput.type()) {
+ if (LinkerConfig::Object == pConfig.codeGenType()) {
//TODO: support incremental linking
;
}
@@ -610,17 +109,19 @@
}
break;
}
- }
+ } // end of for
// perform sorting on m_SectionOrder to get a ordering for final layout
- sortSectionOrder(pOutput, pBackend, pInfo);
+ sortSectionOrder(pBackend, pConfig);
// Backend defines the section start offset for section 1.
uint64_t offset = pBackend.sectionStartOffset();
+ // compute the section offset and handle alignment also. And ignore section 0
+ // (NULL in ELF/COFF), and MachO starts from section 1.
+ // always set NULL section's offset to 0
+ m_SectionOrder[0]->setOffset(0);
for (size_t index = 1; index < m_SectionOrder.size(); ++index) {
- // compute the section offset and handle alignment also. And ignore section 0
- // (NULL in ELF/COFF), and MachO starts from section 1.
if (LDFileFormat::BSS != m_SectionOrder[index - 1]->kind()) {
// we should not preserve file space for the BSS section.
@@ -633,24 +134,12 @@
// FIXME: Currently Writer bases on the section table in output context to
// write out sections, so we have to update its content..
- output_context.getSectionTable().clear();
+ pModule.getSectionTable().clear();
for (size_t index = 0; index < m_SectionOrder.size(); ++index) {
- output_context.getSectionTable().push_back(m_SectionOrder[index]);
+ pModule.getSectionTable().push_back(m_SectionOrder[index]);
// after sorting, update the correct output section indices
m_SectionOrder[index]->setIndex(index);
}
return true;
}
-bool Layout::isValidOffset(const Fragment& pFrag, uint64_t pTargetOffset) const
-{
- uint64_t size = computeFragmentSize(*this, pFrag);
- if (0x0 == size)
- return (pTargetOffset == pFrag.getOffset());
-
- if (NULL != pFrag.getNextNode())
- return (pTargetOffset >= pFrag.getOffset() && pTargetOffset < pFrag.getNextNode()->getOffset());
-
- return (pTargetOffset >= pFrag.getOffset() && pTargetOffset < (pFrag.getOffset() + size));
-}
-
diff --git a/lib/LD/NamePool.cpp b/lib/LD/NamePool.cpp
index 1247057..9e4755d 100644
--- a/lib/LD/NamePool.cpp
+++ b/lib/LD/NamePool.cpp
@@ -8,30 +8,32 @@
//===----------------------------------------------------------------------===//
#include <llvm/Support/raw_ostream.h>
#include <mcld/LD/NamePool.h>
-#include <mcld/LD/Resolver.h>
+#include <mcld/LD/StaticResolver.h>
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// NamePool
-NamePool::NamePool(const Resolver& pResolver, NamePool::size_type pSize)
- : m_pResolver(&pResolver), m_Table(pSize) {
+//===----------------------------------------------------------------------===//
+NamePool::NamePool(NamePool::size_type pSize)
+ : m_pResolver(new StaticResolver()), m_Table(pSize) {
}
NamePool::~NamePool()
{
+ delete m_pResolver;
}
/// createSymbol - create a symbol
ResolveInfo* NamePool::createSymbol(const llvm::StringRef& pName,
- bool pIsDyn,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- ResolveInfo::Visibility pVisibility)
+ bool pIsDyn,
+ ResolveInfo::Type pType,
+ ResolveInfo::Desc pDesc,
+ ResolveInfo::Binding pBinding,
+ ResolveInfo::SizeType pSize,
+ ResolveInfo::Visibility pVisibility)
{
- ResolveInfo* result = m_Table.getEntryFactory().produce(pName);
+ ResolveInfo* result = ResolveInfo::Create(pName);
result->setIsSymbol(true);
result->setSource(pIsDyn);
result->setType(pType);
diff --git a/lib/LD/RelocData.cpp b/lib/LD/RelocData.cpp
new file mode 100644
index 0000000..92192e6
--- /dev/null
+++ b/lib/LD/RelocData.cpp
@@ -0,0 +1,39 @@
+//===- RelocData.cpp ------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/RelocData.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// RelocData
+//===----------------------------------------------------------------------===//
+RelocData::RelocData()
+ : m_pSection(NULL) {
+}
+
+RelocData::RelocData(const LDSection &pSection)
+ : m_pSection(&pSection) {
+}
+
+RelocData* RelocData::Create(const LDSection& pSection)
+{
+ return new RelocData(pSection);
+}
+
+RelocData* RelocData::Create()
+{
+ return new RelocData();
+}
+
+void RelocData::Destroy(RelocData*& pSection)
+{
+ delete pSection;
+ pSection = NULL;
+}
+
diff --git a/lib/LD/RelocationFactory.cpp b/lib/LD/RelocationFactory.cpp
index 828acb2..6fb6cb2 100644
--- a/lib/LD/RelocationFactory.cpp
+++ b/lib/LD/RelocationFactory.cpp
@@ -24,7 +24,7 @@
//===----------------------------------------------------------------------===//
RelocationFactory::RelocationFactory(size_t pNum)
: GCFactory<Relocation, 0>(pNum),
- m_pLayout(NULL) {
+ m_pLinker(NULL) {
}
RelocationFactory::~RelocationFactory()
@@ -83,14 +83,19 @@
/** GCFactory will recycle the relocation **/
}
-void RelocationFactory::setLayout(const Layout& pLayout)
+void RelocationFactory::setFragmentLinker(const FragmentLinker& pLinker)
{
- m_pLayout = &pLayout;
+ m_pLinker = &pLinker;
}
-const Layout& RelocationFactory::getLayout() const
+const FragmentLinker& RelocationFactory::getFragmentLinker() const
{
- assert(0 != m_pLayout);
- return *m_pLayout;
+ assert(NULL != m_pLinker);
+ return *m_pLinker;
+}
+
+bool RelocationFactory::hasFragmentLinker() const
+{
+ return (NULL != m_pLinker);
}
diff --git a/lib/LD/ResolveInfo.cpp b/lib/LD/ResolveInfo.cpp
index b931d19..00df6ae 100644
--- a/lib/LD/ResolveInfo.cpp
+++ b/lib/LD/ResolveInfo.cpp
@@ -6,13 +6,18 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "mcld/LD/ResolveInfo.h"
+#include <mcld/LD/ResolveInfo.h>
+#include <cstdlib>
#include <cstring>
using namespace mcld;
-//==========================
+/// g_NullResolveInfo - a pointer to Null ResolveInfo.
+static ResolveInfo* g_NullResolveInfo = NULL;
+
+//===----------------------------------------------------------------------===//
// ResolveInfo
+//===----------------------------------------------------------------------===//
ResolveInfo::ResolveInfo()
: m_Size(0), m_BitField(0) {
m_Ptr.sym_ptr = 0;
@@ -128,6 +133,11 @@
m_BitField &= ~symbol_flag;
}
+bool ResolveInfo::isNull() const
+{
+ return (this == Null());
+}
+
bool ResolveInfo::isDyn() const
{
return (dynamic_flag == (m_BitField & DYN_MASK));
@@ -226,3 +236,46 @@
return (0 == std::memcmp(m_Name, pKey.data(), length));
}
+//===----------------------------------------------------------------------===//
+// ResolveInfo Factory Methods
+//===----------------------------------------------------------------------===//
+ResolveInfo* ResolveInfo::Create(const ResolveInfo::key_type& pKey)
+{
+ ResolveInfo* result = static_cast<ResolveInfo*>(
+ malloc(sizeof(ResolveInfo)+pKey.size()+1));
+ if (NULL == result)
+ return NULL;
+
+ new (result) ResolveInfo();
+ std::memcpy(result->m_Name, pKey.data(), pKey.size());
+ result->m_Name[pKey.size()] = '\0';
+ result->m_BitField &= ~ResolveInfo::RESOLVE_MASK;
+ result->m_BitField |= (pKey.size() << ResolveInfo::NAME_LENGTH_OFFSET);
+ return result;
+}
+
+void ResolveInfo::Destroy(ResolveInfo*& pInfo)
+{
+ if (pInfo->isNull())
+ return;
+
+ if (NULL != pInfo) {
+ pInfo->~ResolveInfo();
+ free(pInfo);
+ }
+
+ pInfo = NULL;
+}
+
+ResolveInfo* ResolveInfo::Null()
+{
+ if (NULL == g_NullResolveInfo) {
+ g_NullResolveInfo = static_cast<ResolveInfo*>(
+ malloc(sizeof(ResolveInfo) + 1));
+ new (g_NullResolveInfo) ResolveInfo();
+ g_NullResolveInfo->m_Name[0] = '\0';
+ g_NullResolveInfo->m_BitField = 0x0;
+ }
+ return g_NullResolveInfo;
+}
+
diff --git a/lib/LD/ResolveInfoFactory.cpp b/lib/LD/ResolveInfoFactory.cpp
deleted file mode 100644
index feb52a3..0000000
--- a/lib/LD/ResolveInfoFactory.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-//===- ResolveInfoFactory.cpp ---------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/LD/ResolveInfoFactory.h"
-#include <cstring>
-#include <cstdlib>
-
-using namespace mcld;
-
-//==========================
-// ResolveInfoFactory
-ResolveInfoFactory::entry_type*
-ResolveInfoFactory::produce(const ResolveInfoFactory::key_type& pKey)
-{
- entry_type* result = static_cast<entry_type*>(
- malloc(sizeof(entry_type)+pKey.size()+1));
- if (NULL == result)
- return NULL;
-
- new (result) entry_type();
- std::memcpy(result->m_Name, pKey.data(), pKey.size());
- result->m_Name[pKey.size()] = '\0';
- result->m_BitField &= ~ResolveInfo::RESOLVE_MASK;
- result->m_BitField |= (pKey.size() << ResolveInfo::NAME_LENGTH_OFFSET);
- return result;
-}
-
-void ResolveInfoFactory::destroy(ResolveInfoFactory::entry_type* pEntry)
-{
- if (NULL != pEntry) {
- pEntry->~entry_type();
- free(pEntry);
- }
-}
-
diff --git a/lib/LD/SectionData.cpp b/lib/LD/SectionData.cpp
index d1858ba..43800ff 100644
--- a/lib/LD/SectionData.cpp
+++ b/lib/LD/SectionData.cpp
@@ -7,13 +7,40 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/LD/SectionData.h>
+
#include <mcld/LD/LDSection.h>
+#include <mcld/Support/GCFactory.h>
+
+#include <llvm/Support/ManagedStatic.h>
using namespace mcld;
+typedef GCFactory<SectionData, MCLD_SECTIONS_PER_INPUT> SectDataFactory;
+
+static llvm::ManagedStatic<SectDataFactory> g_SectDataFactory;
+
//===----------------------------------------------------------------------===//
// SectionData
//===----------------------------------------------------------------------===//
-SectionData::SectionData(const LDSection &pSection)
- : m_pSection(&pSection), m_Alignment(1) {
+SectionData::SectionData()
+ : m_pSection(NULL) {
}
+
+SectionData::SectionData(LDSection &pSection)
+ : m_pSection(&pSection) {
+}
+
+SectionData* SectionData::Create(LDSection& pSection)
+{
+ SectionData* result = g_SectDataFactory->allocate();
+ new (result) SectionData(pSection);
+ return result;
+}
+
+void SectionData::Destroy(SectionData*& pSection)
+{
+ pSection->~SectionData();
+ g_SectDataFactory->deallocate(pSection);
+ pSection = NULL;
+}
+
diff --git a/lib/LD/SectionMap.cpp b/lib/LD/SectionMap.cpp
deleted file mode 100644
index 7bcd809..0000000
--- a/lib/LD/SectionMap.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-//===- SectionMap.cpp -----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <cassert>
-#include <cstring>
-#include <mcld/LD/SectionMap.h>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// SectionMap
-SectionMap::SectionMap()
-{
-}
-
-SectionMap::~SectionMap()
-{
-}
-
-const std::string& SectionMap::getOutputSectName(const std::string& pInput)
-{
- iterator it;
- for (it = begin(); it != end(); ++it) {
- if (0 == strncmp(pInput.c_str(),
- (*it).inputSubStr.c_str(),
- (*it).inputSubStr.length()))
- break;
- // wildcard to a user-defined output section.
- else if (0 == strcmp("*", (*it).inputSubStr.c_str()))
- break;
- }
- // if still no matching, just let a output seciton has the same input name
- if (it == end())
- return pInput;
- return (*it).outputStr;
-}
-
-bool SectionMap::push_back(const std::string& pInput,
- const std::string& pOutput)
-{
- // Now only check if the mapping exists in the map already
- // TODO: handle the cases such as overriding the exist mapping and drawing
- // exception from the given SECTIONS command
- iterator it;
- for (it = m_SectMap.begin(); it != m_SectMap.end(); ++it) {
- if (pInput == (*it).inputSubStr)
- return false;
- }
- struct Mapping mapping = {
- pInput,
- pOutput,
- };
- m_SectMap.push_back(mapping);
- return true;
-}
-
-SectionMap::iterator SectionMap::find(const std::string& pInput)
-{
- iterator it;
- for (it = begin(); it != end(); ++it) {
- if(pInput == (*it).inputSubStr)
- break;
- }
- return it;
-}
-
-SectionMap::Mapping* SectionMap::at(const std::string& pInput)
-{
- iterator it;
- for (it = begin(); it != end(); ++it) {
- if(pInput == (*it).inputSubStr)
- break;
- }
- if (end() == it)
- return NULL;
- return &(*it);
-}
-
-// Common mappings of ELF and other formants. Now only ELF specific mappings are added
-const SectionMap::SectionNameMapping SectionMap::m_StdSectionMap[] =
-{
- {".text", ".text"},
- {".rodata", ".rodata"},
- {".data.rel.ro.local", ".data.rel.ro.local"},
- {".data.rel.ro", ".data.rel.ro"},
- {".data", ".data"},
- {".bss", ".bss"},
- {".tdata", ".tdata"},
- {".tbss", ".tbss"},
- {".init_array", ".init_array"},
- {".fini_array", ".fini_array"},
- // TODO: Support DT_INIT_ARRAY for all constructors?
- {".ctors", ".ctors"},
- {".dtors", ".dtors"},
- {".sdata", ".sdata"},
- {".sbss", ".sbss"},
- // FIXME: in GNU ld, if we are creating a shared object .sdata2 and .sbss2
- // sections would be handled differently.
- {".sdata2", ".sdata"},
- {".sbss2", ".sbss"},
- {".lrodata", ".lrodata"},
- {".ldata", ".ldata"},
- {".lbss", ".lbss"},
- {".gcc_except_table", ".gcc_except_table"},
- {".gnu.linkonce.d.rel.ro.local", ".data.rel.ro.local"},
- {".gnu.linkonce.d.rel.ro", ".data.rel.ro"},
- {".gnu.linkonce.t", ".text"},
- {".gnu.linkonce.r", ".rodata"},
- {".gnu.linkonce.d", ".data"},
- {".gnu.linkonce.b", ".bss"},
- {".gnu.linkonce.s", ".sdata"},
- {".gnu.linkonce.sb", ".sbss"},
- {".gnu.linkonce.s2", ".sdata"},
- {".gnu.linkonce.sb2", ".sbss"},
- {".gnu.linkonce.wi", ".debug_info"},
- {".gnu.linkonce.td", ".tdata"},
- {".gnu.linkonce.tb", ".tbss"},
- {".gnu.linkonce.lr", ".lrodata"},
- {".gnu.linkonce.l", ".ldata"},
- {".gnu.linkonce.lb", ".lbss"},
-};
-
-const int SectionMap::m_StdSectionMapSize =
- (sizeof(SectionMap::m_StdSectionMap) / sizeof(SectionMap::m_StdSectionMap[0]));
-
-bool SectionMap::initStdSectionMap()
-{
- for (int i = 0; i < m_StdSectionMapSize; ++i) {
- struct Mapping mapping = { m_StdSectionMap[i].from, m_StdSectionMap[i].to};
- m_SectMap.push_back(mapping);
- }
- return true;
-}
diff --git a/lib/LD/SectionMerger.cpp b/lib/LD/SectionMerger.cpp
deleted file mode 100644
index 1817e0b..0000000
--- a/lib/LD/SectionMerger.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-//===- SectionMerger.cpp --------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <cassert>
-#include <cstring>
-#include <mcld/LD/SectionMerger.h>
-
-using namespace mcld;
-
-//==========================
-// SectionMerger
-
-SectionMerger::SectionMerger(SectionMap& pSectionMap, LDContext& pContext)
-: m_SectionNameMap(pSectionMap),
- m_Output(pContext),
- m_LDSectionMap()
-{
-}
-
-SectionMerger::~SectionMerger()
-{
-}
-
-SectionMerger::iterator SectionMerger::find(const std::string& pName)
-{
- if (empty())
- initOutputSectMap();
-
- iterator it;
- for (it = begin(); it != end(); ++it) {
- if (0 == strncmp(pName.c_str(),
- (*it).inputSubStr.c_str(),
- (*it).inputSubStr.length()))
- break;
- // wildcard to a user-defined output section.
- else if(0 == strcmp("*", (*it).inputSubStr.c_str()))
- break;
- }
- return it;
-}
-
-LDSection* SectionMerger::getOutputSectHdr(const std::string& pName)
-{
- LDSection* section;
- iterator it = find(pName);
-
- // check if we can find a matched LDSection.
- // If not, we need to find it in output context. But this should be rare.
- if (it != end())
- section = (*it).outputSection;
- else
- section = m_Output.getSection(pName);
-
- assert(NULL != section);
- return section;
-}
-
-SectionData* SectionMerger::getOutputSectData(const std::string& pName)
-{
- return getOutputSectHdr(pName)->getSectionData();
-}
-
-bool SectionMerger::addMapping(const std::string& pName, LDSection* pSection)
-{
- iterator it = find(pName);
- if (it != end()) {
- assert(NULL == (*it).outputSection);
- (*it).outputSection = pSection;
- return true;
- }
- // the mapping rule is not in SectionMap, and this is handled in getOutputSectHdr.
- return false;
-}
-
-void SectionMerger::initOutputSectMap()
-{
- // Based on SectionMap to initialize the map from a input substr to its
- // associated output LDSection*
- SectionMap::iterator it;
- for (it = m_SectionNameMap.begin(); it != m_SectionNameMap.end(); ++it) {
- struct Mapping mapping = {
- (*it).inputSubStr,
- NULL,
- };
- m_LDSectionMap.push_back(mapping);
- }
- assert(m_SectionNameMap.size() == m_LDSectionMap.size());
-}
diff --git a/lib/LD/SectionRules.cpp b/lib/LD/SectionRules.cpp
new file mode 100644
index 0000000..08c3478
--- /dev/null
+++ b/lib/LD/SectionRules.cpp
@@ -0,0 +1,111 @@
+//===- SectionRules.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/SectionRules.h>
+
+#include <cassert>
+#include <cstring>
+
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/Object/SectionMap.h>
+#include <mcld/ADT/StringHash.h>
+
+using namespace mcld;
+
+namespace {
+ static StringHash<ES> hash_func;
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// SectionRules::Rule
+//===----------------------------------------------------------------------===//
+SectionRules::Rule::Rule(const std::string& pSubStr, LDSection* pSection)
+ : substr(pSubStr), target(pSection) {
+ hash = hash_func(pSubStr);
+}
+
+//===----------------------------------------------------------------------===//
+// SectionRules
+//===----------------------------------------------------------------------===//
+SectionRules::SectionRules(const LinkerConfig& pConfig, Module& pModule)
+ : m_SectionNameMap(pConfig.scripts().sectionMap()),
+ m_Module(pModule) {
+}
+
+SectionRules::~SectionRules()
+{
+}
+
+SectionRules::iterator SectionRules::find(const std::string& pName)
+{
+ uint32_t hash = hash_func(pName);
+ RuleList::iterator rule, rEnd = m_RuleList.end();
+ for (rule = m_RuleList.begin(); rule != rEnd; ++rule) {
+ if (pName.size() < rule->substr.size())
+ continue;
+ if (!StringHash<ES>::may_include(rule->hash, hash))
+ continue;
+
+ if (0 == strncmp(pName.c_str(), rule->substr.c_str(), rule->substr.size()))
+ return rule;
+ }
+ return rule;
+}
+
+SectionRules::const_iterator SectionRules::find(const std::string& pName) const
+{
+ uint32_t hash = hash_func(pName);
+ RuleList::const_iterator rule, rEnd = m_RuleList.end();
+ for (rule = m_RuleList.begin(); rule != rEnd; ++rule) {
+ if (pName.size() < rule->substr.size())
+ continue;
+ if (!StringHash<ES>::may_include(rule->hash, hash))
+ continue;
+
+ if (0 == strncmp(pName.c_str(), rule->substr.c_str(), rule->substr.size()))
+ return rule;
+ }
+ return rule;
+}
+
+LDSection* SectionRules::getMatchedSection(const std::string& pName) const
+{
+ LDSection* section;
+ const_iterator it = find(pName);
+
+ // check if we can find a matched LDSection.
+ // If not, we need to find it in output context. But this should be rare.
+ if (it != m_RuleList.end())
+ section = (*it).target;
+ else
+ section = m_Module.getSection(pName);
+
+ return section;
+}
+
+void SectionRules::append(const std::string& pName, LDSection& pSection)
+{
+ iterator it = find(pName);
+ if (it != m_RuleList.end()) {
+ assert(NULL == (*it).target);
+ (*it).target = &pSection;
+ }
+}
+
+void SectionRules::initOutputSectMap()
+{
+ // Based on SectionMap to initialize the map from a input substr to its
+ // associated output LDSection*
+ SectionMap::const_iterator it;
+ for (it = m_SectionNameMap.begin(); it != m_SectionNameMap.end(); ++it) {
+ Rule rule(it->from, NULL);
+ m_RuleList.push_back(rule);
+ }
+ assert(m_SectionNameMap.size() == m_RuleList.size());
+}
diff --git a/lib/LD/SectionSymbolSet.cpp b/lib/LD/SectionSymbolSet.cpp
new file mode 100644
index 0000000..79f4d78
--- /dev/null
+++ b/lib/LD/SectionSymbolSet.cpp
@@ -0,0 +1,102 @@
+//===- SectionSymbolSet.cpp -----------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/SectionSymbolSet.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/NamePool.h>
+#include <mcld/Fragment/FragmentRef.h>
+#include <mcld/LD/LDFileFormat.h>
+
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// SectionSymbolSet
+//===----------------------------------------------------------------------===//
+
+SectionSymbolSet::SectionSymbolSet()
+{
+ m_pSectionSymbolMap = new SectHashTableType(16);
+}
+
+SectionSymbolSet::~SectionSymbolSet()
+{
+ delete m_pSectionSymbolMap;
+}
+
+bool SectionSymbolSet::add(LDSection& pOutSect, NamePool& pNamePool)
+{
+ // create the resolveInfo for this section symbol
+ llvm::StringRef sym_name = llvm::StringRef(pOutSect.name());
+ ResolveInfo* sym_info = pNamePool.createSymbol(sym_name,
+ false,
+ ResolveInfo::Section,
+ ResolveInfo::Define,
+ ResolveInfo::Local,
+ 0x0, // size
+ ResolveInfo::Default);
+
+ // create the output section symbol and set its fragRef to the first fragment
+ // of the section
+ LDSymbol* sym = LDSymbol::Create(*sym_info);
+ sym_info->setSymPtr(sym);
+
+ // insert the symbol to the Section to Symbol hash map
+ bool exist = false;
+ SectHashTableType::entry_type* entry =
+ m_pSectionSymbolMap->insert(&pOutSect, exist);
+ assert(!exist);
+ entry->setValue(sym);
+
+ return true;
+}
+
+bool SectionSymbolSet::finalize(LDSection& pOutSect,
+ SymbolTable& pSymTab)
+{
+ LDSymbol* sym = get(pOutSect);
+ assert(NULL != sym);
+ FragmentRef* frag_ref = NULL;
+ switch (pOutSect.kind()) {
+ case LDFileFormat::Relocation:
+ frag_ref = FragmentRef::Create(pOutSect.getRelocData()->front(), 0x0);
+ break;
+
+ case LDFileFormat::EhFrame:
+ frag_ref = FragmentRef::Create(
+ pOutSect.getEhFrame()->getSectionData().front(), 0x0);
+ break;
+
+ default:
+ frag_ref = FragmentRef::Create(pOutSect.getSectionData()->front(), 0x0);
+ break;
+ }
+ sym->setFragmentRef(frag_ref);
+ // push symbol into output symbol table
+ pSymTab.add(*sym);
+
+ return true;
+}
+
+LDSymbol* SectionSymbolSet::get(const LDSection& pOutSect)
+{
+ SectHashTableType::iterator entry = m_pSectionSymbolMap->find(&pOutSect);
+ return entry.getEntry()->value();
+}
+
+const LDSymbol* SectionSymbolSet::get(const LDSection& pOutSect) const
+{
+ SectHashTableType::iterator entry = m_pSectionSymbolMap->find(&pOutSect);
+ return entry.getEntry()->value();
+}
+
diff --git a/lib/LD/StubFactory.cpp b/lib/LD/StubFactory.cpp
new file mode 100644
index 0000000..1fc43dd
--- /dev/null
+++ b/lib/LD/StubFactory.cpp
@@ -0,0 +1,128 @@
+//===- StubFactory.cpp ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <mcld/LD/StubFactory.h>
+#include <mcld/LD/BranchIslandFactory.h>
+#include <mcld/LD/BranchIsland.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/RelocationFactory.h>
+#include <mcld/Fragment/Stub.h>
+#include <mcld/Fragment/Relocation.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Fragment/FragmentRef.h>
+
+#include <string>
+using namespace mcld;
+
+StubFactory::StubFactory()
+{
+}
+
+StubFactory::~StubFactory()
+{
+ for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end();
+ it != ie; ++it)
+ delete(*it);
+}
+
+/// addPrototype - register a stub prototype
+void StubFactory::addPrototype(Stub* pPrototype)
+{
+ m_StubPool.push_back(pPrototype);
+}
+
+/// create - create a stub if needed, otherwise return NULL
+Stub* StubFactory::create(Relocation& pReloc,
+ uint64_t pTargetSymValue,
+ FragmentLinker& pLinker,
+ RelocationFactory& pRelocFactory,
+ BranchIslandFactory& pBRIslandFactory)
+{
+ // find if there is a prototype stub for the input relocation
+ Stub* prototype = findPrototype(pReloc,
+ pReloc.place(),
+ pTargetSymValue);
+ if (NULL != prototype) {
+ // find the island for the input relocation
+ BranchIsland* island = pBRIslandFactory.find(*(pReloc.targetRef().frag()));
+ if (NULL == island) {
+ island = pBRIslandFactory.produce(*(pReloc.targetRef().frag()));
+ }
+
+ // find if there is such a stub in the island already
+ assert(NULL != island);
+ Stub* stub = island->findStub(prototype, pReloc);
+ if (NULL != stub) {
+ // reset the branch target to the stub instead!
+ pReloc.setSymInfo(stub->symInfo());
+ }
+ else {
+ // create a stub from the prototype
+ stub = prototype->clone();
+
+ // build a name for stub symbol
+ std::string name("__");
+ name.append(pReloc.symInfo()->name());
+ name.append("_");
+ name.append(stub->name());
+ name.append("@");
+ name.append(island->name());
+
+ // create LDSymbol for the stub
+ LDSymbol* symbol =
+ pLinker.defineSymbol<FragmentLinker::Force,
+ FragmentLinker::Resolve>(name,
+ false, // isDyn
+ ResolveInfo::Function,
+ ResolveInfo::Define,
+ ResolveInfo::Local,
+ stub->size(), // size
+ stub->initSymValue(), // value
+ FragmentRef::Create(*stub, stub->initSymValue()),
+ ResolveInfo::Default);
+ stub->setSymInfo(symbol->resolveInfo());
+
+ // add relocations of this stub (i.e., set the branch target of the stub)
+ for (Stub::fixup_iterator it = stub->fixup_begin(),
+ ie = stub->fixup_end(); it != ie; ++it) {
+
+ Relocation* reloc = pRelocFactory.produce(
+ (*it)->type(),
+ *(FragmentRef::Create(*stub, (*it)->offset())),
+ (*it)->addend());
+ reloc->setSymInfo(pReloc.symInfo());
+ island->addRelocation(*reloc);
+ }
+
+ // add stub to the branch island
+ island->addStub(prototype, pReloc, *stub);
+
+ // reset the branch target of the input reloc to this stub instead!
+ pReloc.setSymInfo(stub->symInfo());
+ return stub;
+ }
+ }
+ return NULL;
+}
+
+/// findPrototype - find if there is a registered stub prototype for the given
+/// relocation
+Stub* StubFactory::findPrototype(const Relocation& pReloc,
+ uint64_t pSource,
+ uint64_t pTargetSymValue)
+{
+ for (StubPoolType::iterator it = m_StubPool.begin(), ie = m_StubPool.end();
+ it != ie; ++it) {
+ if ((*it)->isMyDuty(pReloc, pSource, pTargetSymValue))
+ return (*it);
+ }
+ return NULL;
+}
+
diff --git a/lib/LD/TextDiagnosticPrinter.cpp b/lib/LD/TextDiagnosticPrinter.cpp
index 466d16d..8860099 100644
--- a/lib/LD/TextDiagnosticPrinter.cpp
+++ b/lib/LD/TextDiagnosticPrinter.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/LD/TextDiagnosticPrinter.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
#include <llvm/Support/Signals.h>
#include <string>
@@ -27,8 +27,8 @@
//===----------------------------------------------------------------------===//
// TextDiagnosticPrinter
TextDiagnosticPrinter::TextDiagnosticPrinter(llvm::raw_ostream& pOStream,
- const MCLDInfo& pLDInfo)
- : m_OStream(pOStream), m_LDInfo(pLDInfo), m_pInput(NULL) {
+ const LinkerConfig& pConfig)
+ : m_OStream(pOStream), m_Config(pConfig), m_pInput(NULL) {
}
TextDiagnosticPrinter::~TextDiagnosticPrinter()
@@ -77,7 +77,7 @@
}
case DiagnosticEngine::Debug: {
// show debug message only if verbose >= 0
- if (0 <= m_LDInfo.options().verbose()) {
+ if (0 <= m_Config.options().verbose()) {
m_OStream.changeColor(DebugColor, true);
m_OStream << "Debug: ";
m_OStream.resetColor();
@@ -87,7 +87,7 @@
}
case DiagnosticEngine::Note: {
// show ignored message only if verbose >= 1
- if (1 <= m_LDInfo.options().verbose()) {
+ if (1 <= m_Config.options().verbose()) {
m_OStream.changeColor(NoteColor, true);
m_OStream << "Note: ";
m_OStream.resetColor();
@@ -97,7 +97,7 @@
}
case DiagnosticEngine::Ignore: {
// show ignored message only if verbose >= 2
- if (2 <= m_LDInfo.options().verbose()) {
+ if (2 <= m_Config.options().verbose()) {
m_OStream.changeColor(IgnoreColor, true);
m_OStream << "Ignore: ";
m_OStream.resetColor();
@@ -127,7 +127,7 @@
break;
}
case DiagnosticEngine::Error: {
- int16_t error_limit = m_LDInfo.options().maxErrorNum();
+ int16_t error_limit = m_Config.options().maxErrorNum();
if ((error_limit != -1) &&
(getNumErrors() > static_cast<unsigned>(error_limit))) {
m_OStream << "\n\n";
@@ -140,7 +140,7 @@
break;
}
case DiagnosticEngine::Warning: {
- int16_t warning_limit = m_LDInfo.options().maxWarnNum();
+ int16_t warning_limit = m_Config.options().maxWarnNum();
if ((warning_limit != -1) &&
(getNumWarnings() > static_cast<unsigned>(warning_limit))) {
m_OStream << "\n\n";
@@ -156,7 +156,7 @@
}
}
-void TextDiagnosticPrinter::beginInput(const Input& pInput, const MCLDInfo& pLDInfo)
+void TextDiagnosticPrinter::beginInput(const Input& pInput, const LinkerConfig& pConfig)
{
m_pInput = &pInput;
}
diff --git a/lib/MC/Android.mk b/lib/MC/Android.mk
index 30ca202..0f8911b 100644
--- a/lib/MC/Android.mk
+++ b/lib/MC/Android.mk
@@ -1,19 +1,16 @@
LOCAL_PATH:= $(call my-dir)
mcld_mc_SRC_FILES := \
- AttributeFactory.cpp \
+ Attribute.cpp \
+ AttributeSet.cpp \
+ CommandAction.cpp \
ContextFactory.cpp \
+ FileAction.cpp \
+ InputAction.cpp \
+ InputBuilder.cpp \
InputFactory.cpp \
- InputTree.cpp \
- MCLDAttribute.cpp \
MCLDDirectory.cpp \
- MCLDDriver.cpp \
- MCLDFile.cpp \
- MCLDInfo.cpp \
MCLDInput.cpp \
- MCLDOptions.cpp \
- MCLDOutput.cpp \
- MCLinker.cpp \
SearchDirs.cpp \
SymbolCategory.cpp \
ZOption.cpp
diff --git a/lib/MC/MCLDAttribute.cpp b/lib/MC/Attribute.cpp
similarity index 75%
rename from lib/MC/MCLDAttribute.cpp
rename to lib/MC/Attribute.cpp
index f7b7e47..64782db 100644
--- a/lib/MC/MCLDAttribute.cpp
+++ b/lib/MC/Attribute.cpp
@@ -6,14 +6,15 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/MC/MCLDAttribute.h>
-#include <mcld/MC/AttributeFactory.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/MC/AttributeSet.h>
#include <mcld/Support/MsgHandling.h>
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// AttrConstraint
+//===----------------------------------------------------------------------===//
bool AttrConstraint::isLegal(const Attribute& pAttr) const
{
if (!isWholeArchive() && pAttr.isWholeArchive()) {
@@ -44,10 +45,13 @@
return true;
}
-//==========================
+//===----------------------------------------------------------------------===//
// AttributeProxy
-AttributeProxy::AttributeProxy(AttributeFactory& pParent, Attribute& pBase)
- : m_AttrPool(pParent), m_pBase(&pBase) {
+//===----------------------------------------------------------------------===//
+AttributeProxy::AttributeProxy(AttributeSet& pParent,
+ const Attribute& pBase,
+ const AttrConstraint& pConstraint)
+ : m_AttrPool(pParent), m_pBase(&pBase), m_Constraint(pConstraint) {
}
AttributeProxy::~AttributeProxy()
@@ -56,7 +60,7 @@
bool AttributeProxy::isWholeArchive() const
{
- if (m_AttrPool.constraint().isWholeArchive())
+ if (m_Constraint.isWholeArchive())
return m_pBase->isWholeArchive();
else
return false;
@@ -64,7 +68,7 @@
bool AttributeProxy::isAsNeeded() const
{
- if (m_AttrPool.constraint().isAsNeeded())
+ if (m_Constraint.isAsNeeded())
return m_pBase->isAsNeeded();
else
return false;
@@ -72,7 +76,7 @@
bool AttributeProxy::isAddNeeded() const
{
- if (m_AttrPool.constraint().isAddNeeded())
+ if (m_Constraint.isAddNeeded())
return m_pBase->isAddNeeded();
else
return false;
@@ -80,7 +84,7 @@
bool AttributeProxy::isStatic() const
{
- if (m_AttrPool.constraint().isSharedSystem())
+ if (m_Constraint.isSharedSystem())
return m_pBase->isStatic();
else
return true;
@@ -88,18 +92,18 @@
bool AttributeProxy::isDynamic() const
{
- if (m_AttrPool.constraint().isSharedSystem())
+ if (m_Constraint.isSharedSystem())
return m_pBase->isDynamic();
else
return false;
}
-static inline void ReplaceOrRecord(AttributeFactory& pParent,
- Attribute *&pBase,
+static inline void ReplaceOrRecord(AttributeSet& pParent,
+ const Attribute *&pBase,
Attribute *&pCopy)
{
Attribute *result = pParent.exists(*pCopy);
- if (0 == result) { // can not find
+ if (NULL == result) { // can not find
pParent.record(*pCopy);
pBase = pCopy;
}
@@ -165,8 +169,9 @@
ReplaceOrRecord(m_AttrPool, m_pBase, copy);
}
-AttributeProxy* AttributeProxy::clone() const
+AttributeProxy& AttributeProxy::assign(Attribute* pBase)
{
- return new AttributeProxy(m_AttrPool, *m_pBase);
+ m_pBase = pBase;
+ return *this;
}
diff --git a/lib/MC/AttributeFactory.cpp b/lib/MC/AttributeFactory.cpp
deleted file mode 100644
index f6f4428..0000000
--- a/lib/MC/AttributeFactory.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-//===- AttributeFactory.cpp -----------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDAttribute.h"
-#include "mcld/MC/AttributeFactory.h"
-
-using namespace mcld;
-
-//==========================
-// AttributeFactory
-AttributeFactory::AttributeFactory()
- : m_AttrSet() {
- m_AttrSet.push_back(new mcld::Attribute());
- m_pLast = new AttributeProxy(*this, *m_AttrSet.front());
-}
-
-AttributeFactory::AttributeFactory(size_t pNum)
- : m_AttrSet() {
- m_AttrSet.reserve(pNum);
- m_AttrSet.push_back(new mcld::Attribute());
- m_pLast = new AttributeProxy(*this, *m_AttrSet.front());
-}
-
-AttributeFactory::~AttributeFactory()
-{
- iterator cur = m_AttrSet.begin();
- iterator aEnd = m_AttrSet.end();
- while(cur != aEnd) {
- delete (*cur);
- ++cur;
- }
- m_AttrSet.clear();
- delete m_pLast;
-}
-
-void AttributeFactory::reserve(size_t pNum)
-{
- m_AttrSet.reserve(pNum);
-}
-
-Attribute &AttributeFactory::predefined()
-{
- return *m_AttrSet.front();
-}
-
-const Attribute &AttributeFactory::predefined() const
-{
- return *m_AttrSet.front();
-}
-
-AttributeProxy* AttributeFactory::produce()
-{
- m_pLast->change(m_AttrSet.front());
- return m_pLast->clone();
-}
-
-AttributeProxy& AttributeFactory::last()
-{
- return *m_pLast;
-}
-
-const AttributeProxy& AttributeFactory::last() const
-{
- return *m_pLast;
-}
-
-Attribute* AttributeFactory::exists(const Attribute& pAttr) const
-{
- const_iterator cur = m_AttrSet.begin();
- const_iterator aEnd = m_AttrSet.end();
- while(cur != aEnd) {
- if (*(*cur) == pAttr) {
- m_pLast->change(*cur);
- return *cur;
- }
- ++cur;
- }
- return 0;
-}
-
-void AttributeFactory::record(mcld::Attribute &pAttr)
-{
- m_AttrSet.push_back(&pAttr);
- m_pLast->change(m_AttrSet.back());
-}
-
diff --git a/lib/MC/AttributeSet.cpp b/lib/MC/AttributeSet.cpp
new file mode 100644
index 0000000..e657207
--- /dev/null
+++ b/lib/MC/AttributeSet.cpp
@@ -0,0 +1,54 @@
+//===- AttributeSet.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/MC/Attribute.h>
+#include <mcld/MC/AttributeSet.h>
+#include <cstddef>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// AttributeSet
+//===----------------------------------------------------------------------===//
+AttributeSet::AttributeSet(unsigned int pNum, const Attribute& pPredefined)
+ : m_AttrSet(), m_Predefined(pPredefined) {
+ m_AttrSet.reserve(pNum);
+}
+
+AttributeSet::~AttributeSet()
+{
+ iterator cur = m_AttrSet.begin();
+ iterator aEnd = m_AttrSet.end();
+
+ while(cur != aEnd) {
+ delete (*cur);
+ ++cur;
+ }
+}
+
+Attribute* AttributeSet::exists(const Attribute& pAttr) const
+{
+ if (m_Predefined == pAttr)
+ return const_cast<Attribute*>(&m_Predefined);
+
+ const_iterator cur = m_AttrSet.begin();
+ const_iterator aEnd = m_AttrSet.end();
+ while(cur != aEnd) {
+ if (*(*cur) == pAttr) {
+ return *cur;
+ }
+ ++cur;
+ }
+ return NULL;
+}
+
+void AttributeSet::record(mcld::Attribute &pAttr)
+{
+ m_AttrSet.push_back(&pAttr);
+}
+
diff --git a/lib/MC/CommandAction.cpp b/lib/MC/CommandAction.cpp
new file mode 100644
index 0000000..91b5904
--- /dev/null
+++ b/lib/MC/CommandAction.cpp
@@ -0,0 +1,220 @@
+//===- CommandAction.cpp --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/MC/CommandAction.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/SearchDirs.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/Support/MsgHandling.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// Derived Positional Option
+//===----------------------------------------------------------------------===//
+// InputFileAction
+//===----------------------------------------------------------------------===//
+InputFileAction::InputFileAction(unsigned int pPosition,
+ const sys::fs::Path &pPath)
+ : InputAction(pPosition), m_Path(pPath) {
+}
+
+bool InputFileAction::activate(InputBuilder& pBuilder) const
+{
+ pBuilder.createNode<InputTree::Positional>(path().stem().native(), path());
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// NamespecAction
+//===----------------------------------------------------------------------===//
+NamespecAction::NamespecAction(unsigned int pPosition,
+ const std::string &pNamespec,
+ SearchDirs& pSearchDirs)
+ : InputAction(pPosition), m_Namespec(pNamespec), m_SearchDirs(pSearchDirs) {
+}
+
+bool NamespecAction::activate(InputBuilder& pBuilder) const
+{
+ sys::fs::Path* path = NULL;
+ // find out the real path of the namespec.
+ if (pBuilder.getConstraint().isSharedSystem()) {
+ // In the system with shared object support, we can find both archive
+ // and shared object.
+
+ if (pBuilder.getAttributes().isStatic()) {
+ // with --static, we must search an archive.
+ path = m_SearchDirs.find(namespec(), Input::Archive);
+ }
+ else {
+ // otherwise, with --Bdynamic, we can find either an archive or a
+ // shared object.
+ path = m_SearchDirs.find(namespec(), Input::DynObj);
+ }
+ }
+ else {
+ // In the system without shared object support, we only look for an archive
+ path = m_SearchDirs.find(namespec(), Input::Archive);
+ }
+
+ if (NULL == path) {
+ fatal(diag::err_cannot_find_namespec) << namespec();
+ return false;
+ }
+
+ pBuilder.createNode<InputTree::Positional>(namespec(), *path);
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// BitcodeAction
+//===----------------------------------------------------------------------===//
+BitcodeAction::BitcodeAction(unsigned int pPosition, const sys::fs::Path &pPath)
+ : InputAction(pPosition), m_Path(pPath) {
+}
+
+bool BitcodeAction::activate(InputBuilder& pBuilder) const
+{
+ pBuilder.createNode<InputTree::Positional>("bitcode", path(), Input::External);
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// StartGroupAction
+//===----------------------------------------------------------------------===//
+StartGroupAction::StartGroupAction(unsigned int pPosition)
+ : InputAction(pPosition) {
+}
+
+bool StartGroupAction::activate(InputBuilder& pBuilder) const
+{
+ if (pBuilder.isInGroup()) {
+ fatal(diag::fatal_forbid_nest_group);
+ return false;
+ }
+ pBuilder.enterGroup();
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// EndGroupAction
+//===----------------------------------------------------------------------===//
+EndGroupAction::EndGroupAction(unsigned int pPosition)
+ : InputAction(pPosition) {
+}
+
+bool EndGroupAction::activate(InputBuilder& pBuilder) const
+{
+ pBuilder.exitGroup();
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// WholeArchiveAction
+//===----------------------------------------------------------------------===//
+WholeArchiveAction::WholeArchiveAction(unsigned int pPosition)
+ : InputAction(pPosition) {
+}
+
+bool WholeArchiveAction::activate(InputBuilder& pBuilder) const
+{
+ pBuilder.getAttributes().setWholeArchive();
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// NoWholeArchiveAction
+//===----------------------------------------------------------------------===//
+NoWholeArchiveAction::NoWholeArchiveAction(unsigned int pPosition)
+ : InputAction(pPosition) {
+}
+
+bool NoWholeArchiveAction::activate(InputBuilder& pBuilder) const
+{
+ pBuilder.getAttributes().unsetWholeArchive();
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// AsNeededAction
+//===----------------------------------------------------------------------===//
+AsNeededAction::AsNeededAction(unsigned int pPosition)
+ : InputAction(pPosition) {
+}
+
+bool AsNeededAction::activate(InputBuilder& pBuilder) const
+{
+ pBuilder.getAttributes().setAsNeeded();
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// NoAsNeededAction
+//===----------------------------------------------------------------------===//
+NoAsNeededAction::NoAsNeededAction(unsigned int pPosition)
+ : InputAction(pPosition) {
+}
+
+bool NoAsNeededAction::activate(InputBuilder& pBuilder) const
+{
+ pBuilder.getAttributes().unsetAsNeeded();
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// AddNeededAction
+//===----------------------------------------------------------------------===//
+AddNeededAction::AddNeededAction(unsigned int pPosition)
+ : InputAction(pPosition) {
+}
+
+bool AddNeededAction::activate(InputBuilder& pBuilder) const
+{
+ pBuilder.getAttributes().setAddNeeded();
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// NoAddNeededAction
+//===----------------------------------------------------------------------===//
+NoAddNeededAction::NoAddNeededAction(unsigned int pPosition)
+ : InputAction(pPosition) {
+}
+
+bool NoAddNeededAction::activate(InputBuilder& pBuilder) const
+{
+ pBuilder.getAttributes().unsetAddNeeded();
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// BDynamicAction
+//===----------------------------------------------------------------------===//
+BDynamicAction::BDynamicAction(unsigned int pPosition)
+ : InputAction(pPosition) {
+}
+
+bool BDynamicAction::activate(InputBuilder& pBuilder) const
+{
+ pBuilder.getAttributes().setDynamic();
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// BStaticAction
+//===----------------------------------------------------------------------===//
+BStaticAction::BStaticAction(unsigned int pPosition)
+ : InputAction(pPosition) {
+}
+
+bool BStaticAction::activate(InputBuilder& pBuilder) const
+{
+ pBuilder.getAttributes().setStatic();
+ return true;
+}
+
diff --git a/lib/MC/FileAction.cpp b/lib/MC/FileAction.cpp
new file mode 100644
index 0000000..8660558
--- /dev/null
+++ b/lib/MC/FileAction.cpp
@@ -0,0 +1,66 @@
+//===- FileAction.cpp -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/MC/FileAction.h>
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/ContextFactory.h>
+#include <mcld/Support/MemoryAreaFactory.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ContextAction
+//===----------------------------------------------------------------------===//
+ContextAction::ContextAction(unsigned int pPosition)
+ : InputAction(pPosition) {
+}
+
+bool ContextAction::activate(InputBuilder& pBuilder) const
+{
+ Input* input = *pBuilder.getCurrentNode();
+
+ if (input->hasContext())
+ return false;
+
+ // already got type - for example, bitcode
+ if (input->type() == Input::Script ||
+ input->type() == Input::Object ||
+ input->type() == Input::DynObj ||
+ input->type() == Input::Archive)
+ return false;
+
+ return pBuilder.setContext(*input);
+}
+
+//===----------------------------------------------------------------------===//
+// MemoryAreaAction
+//===----------------------------------------------------------------------===//
+MemoryAreaAction::MemoryAreaAction(unsigned int pPosition,
+ FileHandle::OpenMode pMode,
+ FileHandle::Permission pPerm)
+ : InputAction(pPosition), m_Mode(pMode), m_Permission(pPerm) {
+}
+
+bool MemoryAreaAction::activate(InputBuilder& pBuilder) const
+{
+ Input* input = *pBuilder.getCurrentNode();
+
+ if (input->hasMemArea())
+ return false;
+
+ // already got type - for example, bitcode
+ if (input->type() == Input::Script ||
+ input->type() == Input::Object ||
+ input->type() == Input::DynObj ||
+ input->type() == Input::Archive)
+ return false;
+
+ return pBuilder.setMemory(*input, m_Mode, m_Permission);
+}
+
diff --git a/lib/LD/CIE.cpp b/lib/MC/InputAction.cpp
similarity index 64%
rename from lib/LD/CIE.cpp
rename to lib/MC/InputAction.cpp
index 5ddb166..f9078c6 100644
--- a/lib/LD/CIE.cpp
+++ b/lib/MC/InputAction.cpp
@@ -1,4 +1,4 @@
-//===- CIE.cpp ------------------------------------------------------------===//
+//===- InputAction.cpp ----------------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,18 +6,18 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/CIE.h>
+#include <mcld/MC/InputAction.h>
using namespace mcld;
//===----------------------------------------------------------------------===//
-// CIE
+// Base Positional Option
//===----------------------------------------------------------------------===//
-CIE::CIE(MemoryRegion& pRegion, uint8_t pFDEEncode)
- : RegionFragment(pRegion), m_FDEEncoding(pFDEEncode) {
+InputAction::InputAction(unsigned int pPosition)
+ : m_Position(pPosition) {
}
-CIE::~CIE()
+InputAction::~InputAction()
{
}
+
diff --git a/lib/MC/InputBuilder.cpp b/lib/MC/InputBuilder.cpp
new file mode 100644
index 0000000..9142801
--- /dev/null
+++ b/lib/MC/InputBuilder.cpp
@@ -0,0 +1,163 @@
+//===- InputBuilder.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/MC/InputBuilder.h>
+
+#include <mcld/LinkerConfig.h>
+#include <mcld/Config/Config.h>
+#include <mcld/Support/Path.h>
+#include <mcld/MC/InputFactory.h>
+#include <mcld/MC/ContextFactory.h>
+#include <mcld/Support/MemoryAreaFactory.h>
+
+using namespace mcld;
+
+InputBuilder::InputBuilder(const LinkerConfig& pConfig)
+ : m_Config(pConfig),
+ m_pCurrentTree(NULL), m_pMove(NULL), m_Root(),
+ m_bOwnFactory(true) {
+
+ m_pInputFactory = new InputFactory(MCLD_NUM_OF_INPUTS, pConfig);
+ m_pContextFactory = new ContextFactory(MCLD_NUM_OF_INPUTS);
+ m_pMemFactory = new MemoryAreaFactory(MCLD_NUM_OF_INPUTS);
+}
+
+InputBuilder::InputBuilder(const LinkerConfig& pConfig,
+ InputFactory& pInputFactory,
+ ContextFactory& pContextFactory,
+ MemoryAreaFactory& pMemoryFactory,
+ bool pDelegate)
+ : m_Config(pConfig),
+ m_pInputFactory(&pInputFactory),
+ m_pMemFactory(&pMemoryFactory),
+ m_pContextFactory(&pContextFactory),
+ m_pCurrentTree(NULL), m_pMove(NULL), m_Root(),
+ m_bOwnFactory(pDelegate) {
+
+}
+
+InputBuilder::~InputBuilder()
+{
+ if (m_bOwnFactory) {
+ delete m_pInputFactory;
+ delete m_pContextFactory;
+ delete m_pMemFactory;
+ }
+}
+
+Input* InputBuilder::createInput(const std::string& pName,
+ const sys::fs::Path& pPath,
+ unsigned int pType,
+ off_t pFileOffset)
+{
+ return m_pInputFactory->produce(pName, pPath, pType, pFileOffset);
+}
+
+InputTree& InputBuilder::enterGroup()
+{
+ assert(NULL != m_pCurrentTree && NULL != m_pMove);
+
+ m_pCurrentTree->enterGroup(m_Root, *m_pMove);
+ m_pMove->move(m_Root);
+ m_ReturnStack.push(m_Root);
+ m_pMove = &InputTree::Downward;
+
+ return *m_pCurrentTree;
+}
+
+InputTree& InputBuilder::exitGroup()
+{
+ assert(NULL != m_pCurrentTree && NULL != m_pMove);
+
+ m_Root = m_ReturnStack.top();
+ m_ReturnStack.pop();
+ m_pMove = &InputTree::Afterward;
+
+ return *m_pCurrentTree;
+}
+
+bool InputBuilder::isInGroup() const
+{
+ return !m_ReturnStack.empty();
+}
+
+const InputTree& InputBuilder::getCurrentTree() const
+{
+ assert(NULL != m_pCurrentTree && NULL != m_pMove);
+ return *m_pCurrentTree;
+}
+
+InputTree& InputBuilder::getCurrentTree()
+{
+ assert(NULL != m_pCurrentTree && NULL != m_pMove);
+ return *m_pCurrentTree;
+}
+
+void InputBuilder::setCurrentTree(InputTree& pInputTree)
+{
+ m_pCurrentTree = &pInputTree;
+ m_Root = m_pCurrentTree->root();
+ m_pMove = &InputTree::Downward;
+}
+
+bool InputBuilder::setContext(Input& pInput, bool pCheck)
+{
+ // The object files in an archive have common path. Every object files in an
+ // archive needs a individual context. We identify the object files in an
+ // archive by its file offset. Their file offsets are not zero.
+ LDContext* context = NULL;
+ if (0 != pInput.fileOffset() || !pCheck) {
+ // pInput is an object in an archive file. Produce a new context in this
+ // case.
+ context = m_pContextFactory->produce();
+ }
+ else {
+ // Using pInput.path() to avoid from creating context for identical file
+ // twice.
+ context = m_pContextFactory->produce(pInput.path());
+ }
+
+ pInput.setContext(context);
+ return true;
+}
+
+bool InputBuilder::setMemory(Input& pInput,
+ FileHandle::OpenMode pMode,
+ FileHandle::Permission pPerm)
+{
+ MemoryArea *memory = m_pMemFactory->produce(pInput.path(), pMode, pPerm);
+
+ if (!memory->handler()->isGood())
+ return false;
+
+ pInput.setMemArea(memory);
+ return true;
+}
+
+bool InputBuilder::setMemory(Input& pInput, void* pMemBuffer, size_t pSize)
+{
+ MemoryArea *memory = m_pMemFactory->produce(pMemBuffer, pSize);
+ pInput.setMemArea(memory);
+ return true;
+}
+
+const AttrConstraint& InputBuilder::getConstraint() const
+{
+ return m_Config.attribute().constraint();
+}
+
+const AttributeProxy& InputBuilder::getAttributes() const
+{
+ return m_pInputFactory->attr();
+}
+
+AttributeProxy& InputBuilder::getAttributes()
+{
+ return m_pInputFactory->attr();
+}
+
diff --git a/lib/MC/InputFactory.cpp b/lib/MC/InputFactory.cpp
index d4d9cc2..b0b7aaa 100644
--- a/lib/MC/InputFactory.cpp
+++ b/lib/MC/InputFactory.cpp
@@ -6,19 +6,29 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "mcld/MC/InputFactory.h"
-#include "mcld/MC/AttributeFactory.h"
+#include <mcld/MC/InputFactory.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/MC/AttributeSet.h>
+#include <mcld/AttributeOption.h>
using namespace mcld;
//===----------------------------------------------------------------------===//
// InputFactory
-InputFactory::InputFactory(size_t pNum, AttributeFactory& pAttrFactory)
- : GCFactory<Input,0>(pNum), m_AttrFactory(pAttrFactory) {
+//===----------------------------------------------------------------------===//
+InputFactory::InputFactory(size_t pNum, const LinkerConfig& pConfig)
+ : GCFactory<Input,0>(pNum) {
+
+ m_pAttrSet = new AttributeSet(16, pConfig.attribute().predefined());
+ m_pLast = new AttributeProxy(*m_pAttrSet,
+ pConfig.attribute().predefined(),
+ pConfig.attribute().constraint());
}
InputFactory::~InputFactory()
{
+ delete m_pAttrSet;
+ delete m_pLast;
}
Input* InputFactory::produce(llvm::StringRef pName,
@@ -26,8 +36,8 @@
unsigned int pType,
off_t pFileOffset)
{
- mcld::Input* result = Alloc::allocate();
- new (result) mcld::Input(pName, pPath, m_AttrFactory.last(), pType, pFileOffset);
+ Input* result = Alloc::allocate();
+ new (result) Input(pName, pPath, *m_pLast, pType, pFileOffset);
return result;
}
diff --git a/lib/MC/MCLDDriver.cpp b/lib/MC/MCLDDriver.cpp
deleted file mode 100644
index a1af124..0000000
--- a/lib/MC/MCLDDriver.cpp
+++ /dev/null
@@ -1,329 +0,0 @@
-//===- MCLDDriver.cpp -----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/MC/InputTree.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/MC/MCLDDriver.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/LD/ArchiveReader.h>
-#include <mcld/LD/ObjectReader.h>
-#include <mcld/LD/DynObjReader.h>
-#include <mcld/LD/ObjectWriter.h>
-#include <mcld/LD/DynObjWriter.h>
-#include <mcld/LD/ExecWriter.h>
-#include <mcld/LD/ResolveInfo.h>
-#include <mcld/Support/RealPath.h>
-#include <mcld/Support/MemoryAreaFactory.h>
-#include <mcld/Target/TargetLDBackend.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/LD/Archive.h>
-
-using namespace llvm;
-using namespace mcld;
-
-MCLDDriver::MCLDDriver(MCLDInfo& pLDInfo,
- TargetLDBackend& pLDBackend,
- MemoryAreaFactory& pAreaFactory)
- : m_LDInfo(pLDInfo),
- m_LDBackend(pLDBackend),
- m_pLinker(NULL),
- m_AreaFactory(pAreaFactory) {
-
-}
-
-MCLDDriver::~MCLDDriver()
-{
- if (NULL != m_pLinker)
- delete m_pLinker;
-}
-
-/// initMCLinker - initialize MCLinker
-/// Connect all components with MCLinker
-bool MCLDDriver::initMCLinker()
-{
- if (0 == m_pLinker)
- m_pLinker = new MCLinker(m_LDBackend,
- m_LDInfo,
- m_SectionMap);
-
- // initialize the readers and writers
- // Because constructor can not be failed, we initalize all readers and
- // writers outside the MCLinker constructors.
- if (!m_LDBackend.initObjectReader(*m_pLinker) ||
- !m_LDBackend.initArchiveReader(*m_pLinker, m_LDInfo, m_AreaFactory) ||
- !m_LDBackend.initObjectReader(*m_pLinker) ||
- !m_LDBackend.initDynObjReader(*m_pLinker) ||
- !m_LDBackend.initObjectWriter(*m_pLinker) ||
- !m_LDBackend.initDynObjWriter(*m_pLinker) ||
- !m_LDBackend.initExecWriter(*m_pLinker))
- return false;
-
- // initialize RelocationFactory
- m_LDBackend.initRelocFactory(*m_pLinker);
- return true;
-}
-
-/// initStdSections - initialize standard sections
-bool MCLDDriver::initStdSections()
-{
- /// initialize section mapping for standard format, target-dependent section,
- /// (and user-defined mapping)
- if (!m_SectionMap.initStdSectionMap() ||
- !m_LDBackend.initTargetSectionMap(m_SectionMap))
- return false;
-
- /// A technical debt. We need to initialize section map here because
- /// we do not separate output file and temporary data structure. So far,
- /// MCLinker directly use output file's LDContext as the temporary data
- /// structure. We will create a new data structure mcld::Module to collect
- /// all temporary data structures togather.
- m_pLinker->initSectionMap();
-
- // initialize standard sections
- switch (m_LDInfo.output().type()) {
- case Output::DynObj: {
- // intialize standard and target-dependent sections
- if (!m_LDBackend.initDynObjSections(*m_pLinker))
- return false;
- break;
- }
- case Output::Exec: {
- // intialize standard and target-dependent sections
- if (!m_LDBackend.initExecSections(*m_pLinker))
- return false;
- break;
- }
- case Output::Object: {
- llvm::report_fatal_error(llvm::Twine("output type is not implemented yet. file: `") +
- m_LDInfo.output().name() +
- llvm::Twine("'."));
- return false;
- }
- default: {
- llvm::report_fatal_error(llvm::Twine("unknown output type of file `") +
- m_LDInfo.output().name() +
- llvm::Twine("'."));
- return false;
- }
- } // end of switch
-
- // initialize target-dependent sections
- m_LDBackend.initTargetSections(*m_pLinker);
-
- return true;
-}
-
-void MCLDDriver::normalize()
-{
- // ----- set up inputs ----- //
- InputTree::iterator input, inEnd = m_LDInfo.inputs().end();
- for (input = m_LDInfo.inputs().begin(); input!=inEnd; ++input) {
- // already got type - for example, bitcode or external OIR (object
- // intermediate representation)
- if ((*input)->type() == Input::Script ||
- (*input)->type() == Input::Object ||
- (*input)->type() == Input::DynObj ||
- (*input)->type() == Input::Archive ||
- (*input)->type() == Input::External)
- continue;
-
- // is a relocatable object file
- if (m_LDBackend.getObjectReader()->isMyFormat(**input)) {
- (*input)->setType(Input::Object);
- m_LDBackend.getObjectReader()->readObject(**input);
- m_LDBackend.getObjectReader()->readSections(**input);
- m_LDBackend.getObjectReader()->readSymbols(**input);
- }
- // is a shared object file
- else if (m_LDBackend.getDynObjReader()->isMyFormat(**input)) {
- (*input)->setType(Input::DynObj);
- m_LDBackend.getDynObjReader()->readDSO(**input);
- m_LDBackend.getDynObjReader()->readSymbols(**input);
- }
- // is an archive
- else if (m_LDBackend.getArchiveReader()->isMyFormat(**input)) {
- (*input)->setType(Input::Archive);
- Archive archive(**input, m_LDInfo.inputFactory());
- m_LDBackend.getArchiveReader()->readArchive(archive);
- if(archive.numOfObjectMember() > 0) {
- m_LDInfo.inputs().merge<InputTree::Inclusive>(input, archive.inputs());
- }
- }
- else {
- fatal(diag::err_unrecognized_input_file) << (*input)->path()
- << m_LDInfo.triple().str();
- }
- } // end of for
-}
-
-bool MCLDDriver::linkable() const
-{
- // check we have input and output files
- if (m_LDInfo.inputs().empty()) {
- error(diag::err_no_inputs);
- return false;
- }
-
- // check all attributes are legal
- mcld::AttributeFactory::const_iterator attr, attrEnd = m_LDInfo.attrFactory().end();
- for (attr=m_LDInfo.attrFactory().begin(); attr!=attrEnd; ++attr) {
- if (!m_LDInfo.attrFactory().constraint().isLegal((**attr))) {
- return false;
- }
- }
-
- // can not mix -static with shared objects
- mcld::InputTree::const_bfs_iterator input, inEnd = m_LDInfo.inputs().bfs_end();
- for (input=m_LDInfo.inputs().bfs_begin(); input!=inEnd; ++input) {
- if ((*input)->type() == mcld::Input::DynObj) {
- if((*input)->attribute()->isStatic()) {
- error(diag::err_mixed_shared_static_objects)
- << (*input)->name() << (*input)->path();
- return false;
- }
- }
- }
-
- // can not mix -r with shared objects
- return true;
-}
-
-/// mergeSections - put allinput sections into output sections
-bool MCLDDriver::mergeSections()
-{
- // TODO: when MCLinker can read other object files, we have to merge
- // sections
- return true;
-}
-
-/// addStandardSymbols - shared object and executable files need some
-/// standard symbols
-/// @return if there are some input symbols with the same name to the
-/// standard symbols, return false
-bool MCLDDriver::addStandardSymbols()
-{
- return m_LDBackend.initStandardSymbols(*m_pLinker, m_LDInfo.output());
-}
-
-/// addTargetSymbols - some targets, such as MIPS and ARM, need some
-/// target-dependent symbols
-/// @return if there are some input symbols with the same name to the
-/// target symbols, return false
-bool MCLDDriver::addTargetSymbols()
-{
- m_LDBackend.initTargetSymbols(*m_pLinker, m_LDInfo.output());
- return true;
-}
-
-/// readRelocations - read all relocation entries
-///
-/// All symbols should be read and resolved before this function.
-bool MCLDDriver::readRelocations()
-{
- // Bitcode is read by the other path. This function reads relocation sections
- // in object files.
- mcld::InputTree::bfs_iterator input, inEnd = m_LDInfo.inputs().bfs_end();
- for (input=m_LDInfo.inputs().bfs_begin(); input!=inEnd; ++input) {
- if ((*input)->type() == Input::Object) {
- if (!m_LDBackend.getObjectReader()->readRelocations(**input))
- return false;
- }
- // ignore the other kinds of files.
- }
- return true;
-}
-
-/// prelayout - help backend to do some modification before layout
-bool MCLDDriver::prelayout()
-{
- m_LDBackend.preLayout(m_LDInfo.output(),
- m_LDInfo,
- *m_pLinker);
-
- m_LDBackend.allocateCommonSymbols(m_LDInfo, *m_pLinker);
-
- /// check program interpreter - computer the name size of the runtime dyld
- /// FIXME: check if we are doing static linking!
- if (m_LDInfo.output().type() == Output::Exec)
- m_LDBackend.sizeInterp(m_LDInfo.output(), m_LDInfo);
-
- /// measure NamePools - compute the size of name pool sections
- /// In ELF, will compute the size of.symtab, .strtab, .dynsym, .dynstr,
- /// and .hash sections.
- ///
- /// dump all symbols and strings from MCLinker and build the format-dependent
- /// hash table.
- m_LDBackend.sizeNamePools(m_LDInfo.output(), m_pLinker->getOutputSymbols(), m_LDInfo);
-
- return true;
-}
-
-/// layout - linearly layout all output sections and reserve some space
-/// for GOT/PLT
-/// Because we do not support instruction relaxing in this early version,
-/// if there is a branch can not jump to its target, we return false
-/// directly
-bool MCLDDriver::layout()
-{
- return m_pLinker->layout();
-}
-
-/// prelayout - help backend to do some modification after layout
-bool MCLDDriver::postlayout()
-{
- m_LDBackend.postLayout(m_LDInfo.output(),
- m_LDInfo,
- *m_pLinker);
- return true;
-}
-
-/// finalizeSymbolValue - finalize the resolved symbol value.
-/// Before relocate(), after layout(), MCLinker should correct value of all
-/// symbol.
-bool MCLDDriver::finalizeSymbolValue()
-{
- return m_pLinker->finalizeSymbols();
-}
-
-/// relocate - applying relocation entries and create relocation
-/// section in the output files
-/// Create relocation section, asking TargetLDBackend to
-/// read the relocation information into RelocationEntry
-/// and push_back into the relocation section
-bool MCLDDriver::relocation()
-{
- return m_pLinker->applyRelocations();
-}
-
-/// emitOutput - emit the output file.
-bool MCLDDriver::emitOutput()
-{
- switch(m_LDInfo.output().type()) {
- case Output::Object:
- m_LDBackend.getObjectWriter()->writeObject(m_LDInfo.output());
- return true;
- case Output::DynObj:
- m_LDBackend.getDynObjWriter()->writeDynObj(m_LDInfo.output());
- return true;
- case Output::Exec:
- m_LDBackend.getExecWriter()->writeExecutable(m_LDInfo.output());
- return true;
- }
- return false;
-}
-
-/// postProcessing - do modification after all processes
-bool MCLDDriver::postProcessing()
-{
- m_pLinker->syncRelocationResult();
-
- m_LDBackend.postProcessing(m_LDInfo.output(),
- m_LDInfo,
- *m_pLinker);
- return true;
-}
diff --git a/lib/MC/MCLDFile.cpp b/lib/MC/MCLDFile.cpp
deleted file mode 100644
index e6bbbc4..0000000
--- a/lib/MC/MCLDFile.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-//===- MCLDFile.cpp -------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDFile.h"
-#include "mcld/LD/LDContext.h"
-#include "mcld/Support/FileSystem.h"
-#include "mcld/Support/MemoryArea.h"
-#include <cstring>
-#include <cstdlib>
-
-using namespace mcld;
-
-//===----------------------------------------------------------------------===//
-// MCLDFile
-MCLDFile::MCLDFile()
- : m_Type(Unknown), m_pContext(0), m_Path(), m_Name(), m_pMemArea(0) {
-}
-
-MCLDFile::MCLDFile(llvm::StringRef pName)
- : m_Type(Unknown), m_pContext(0), m_Path(), m_Name(pName.data()), m_pMemArea(0) {
-}
-
-MCLDFile::MCLDFile(llvm::StringRef pName,
- const sys::fs::Path& pPath,
- unsigned int pType)
- : m_Type(pType), m_pContext(0), m_Path(pPath), m_Name(pName.data()), m_pMemArea(0) {
-}
-
-MCLDFile::~MCLDFile()
-{
-}
-
-void MCLDFile::setSOName(const std::string& pName)
-{
- size_t pos = pName.find_last_of(sys::fs::separator);
- if (std::string::npos == pos)
- m_Name = pName;
- else
- m_Name = pName.substr(pos + 1);
-}
-
diff --git a/lib/MC/MCLDInfo.cpp b/lib/MC/MCLDInfo.cpp
deleted file mode 100644
index 7ac154c..0000000
--- a/lib/MC/MCLDInfo.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-//===- MCLDInfo.cpp -------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Config/Config.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/InputFactory.h>
-#include <mcld/MC/AttributeFactory.h>
-#include <mcld/MC/ContextFactory.h>
-#include <mcld/LD/NamePool.h>
-#include <mcld/LD/StaticResolver.h>
-#include <mcld/Support/FileSystem.h>
-#include <string>
-
-using namespace mcld;
-
-//==========================
-// MCLDInfo
-MCLDInfo::MCLDInfo(const std::string& pTripleString,
- size_t pAttrNum,
- size_t pInputNum)
- : m_Options(),
- m_Scripts(),
- m_pBitcode(NULL),
- m_Triple(pTripleString)
-{
- m_pAttrFactory = new AttributeFactory(pAttrNum);
- m_pCntxtFactory = new ContextFactory(pInputNum);
- m_pInputFactory = new InputFactory(pInputNum, *m_pAttrFactory);
- m_pInputTree = new InputTree(*m_pInputFactory);
- m_pOutput = new mcld::Output();
- m_pResolver = new StaticResolver();
- m_pNamePool = new NamePool(*m_pResolver, 1024);
-}
-
-MCLDInfo::~MCLDInfo()
-{
- delete m_pOutput;
- delete m_pAttrFactory;
- delete m_pCntxtFactory;
- delete m_pInputFactory;
- delete m_pInputTree;
- delete m_pResolver;
- delete m_pNamePool;
-}
-
-void MCLDInfo::setBitcode(const Input& pInput)
-{
- m_pBitcode = const_cast<Input*>(&pInput);
-}
-
-Input& MCLDInfo::bitcode()
-{
- assert((0 != m_pBitcode) && "default bitcode is not set");
- return *m_pBitcode;
-}
-
-const Input& MCLDInfo::bitcode() const
-{
- assert((0 != m_pBitcode) && "default bitcode is not set");
- return *m_pBitcode;
-}
-
-const char* MCLDInfo::version()
-{
- return MCLD_VERSION;
-}
diff --git a/lib/MC/MCLDInput.cpp b/lib/MC/MCLDInput.cpp
index 0803e00..1fc6cb5 100644
--- a/lib/MC/MCLDInput.cpp
+++ b/lib/MC/MCLDInput.cpp
@@ -6,18 +6,49 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDInput.h"
-#include "mcld/MC/MCLDAttribute.h"
+#include <mcld/MC/MCLDInput.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/LD/LDContext.h>
using namespace mcld;
-//==========================
-// MCInput
+//===----------------------------------------------------------------------===//
+// mcld::Input
+//===----------------------------------------------------------------------===//
+Input::Input(llvm::StringRef pName)
+ : m_Type(Unknown),
+ m_Name(pName.data()),
+ m_Path(),
+ m_pAttr(NULL),
+ m_bNeeded(false),
+ m_fileOffset(0),
+ m_pMemArea(NULL),
+ m_pContext(NULL) {
+}
+
Input::Input(llvm::StringRef pName, const AttributeProxy& pProxy)
- : MCLDFile(pName),
- m_pAttr(const_cast<Attribute*>(pProxy.attr())),
- m_bNeeded(false),
- m_fileOffset(0) {
+ : m_Type(Unknown),
+ m_Name(pName.data()),
+ m_Path(),
+ m_pAttr(const_cast<Attribute*>(pProxy.attr())),
+ m_bNeeded(false),
+ m_fileOffset(0),
+ m_pMemArea(NULL),
+ m_pContext(NULL) {
+}
+
+Input::Input(llvm::StringRef pName,
+ const sys::fs::Path& pPath,
+ unsigned int pType,
+ off_t pFileOffset)
+ : m_Type(pType),
+ m_Name(pName.data()),
+ m_Path(pPath),
+ m_pAttr(NULL),
+ m_bNeeded(false),
+ m_fileOffset(pFileOffset),
+ m_pMemArea(NULL),
+ m_pContext(NULL) {
}
Input::Input(llvm::StringRef pName,
@@ -25,14 +56,19 @@
const AttributeProxy& pProxy,
unsigned int pType,
off_t pFileOffset)
- : MCLDFile(pName, pPath, pType),
+ : m_Type(pType),
+ m_Name(pName.data()),
+ m_Path(pPath),
m_pAttr(const_cast<Attribute*>(pProxy.attr())),
m_bNeeded(false),
- m_fileOffset(pFileOffset) {
+ m_fileOffset(pFileOffset),
+ m_pMemArea(NULL),
+ m_pContext(NULL) {
}
Input::~Input()
{
- // do nothing. Attribute is deleted by AttributeFactory
+ // Attribute is deleted by AttributeFactory
+ // MemoryArea is deleted by MemoryAreaFactory
}
diff --git a/lib/MC/MCLDOutput.cpp b/lib/MC/MCLDOutput.cpp
deleted file mode 100644
index c27ee01..0000000
--- a/lib/MC/MCLDOutput.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-//===- MCLDOutput.cpp -----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/MC/MCLDOutput.h"
-
-using namespace mcld;
-
-//==========================
-// MCLDOutput
-Output::Output()
- : MCLDFile("") {
-}
-
-Output::Output(const sys::fs::Path& pRealPath,
- Output::Type pType)
- : MCLDFile("", pRealPath, pType) {
-}
-
-Output::~Output()
-{
-}
-
diff --git a/lib/MC/MCLinker.cpp b/lib/MC/MCLinker.cpp
deleted file mode 100644
index e9fb327..0000000
--- a/lib/MC/MCLinker.cpp
+++ /dev/null
@@ -1,718 +0,0 @@
-//===- MCLinker.cpp -------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the MCLinker class
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/MC/MCLinker.h>
-
-#include <llvm/Support/Host.h>
-#include <llvm/Support/raw_ostream.h>
-
-#include <mcld/MC/MCLDInput.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/LD/Resolver.h>
-#include <mcld/LD/LDContext.h>
-#include <mcld/LD/LDSymbol.h>
-#include <mcld/LD/LDSectionFactory.h>
-#include <mcld/LD/SectionMap.h>
-#include <mcld/LD/RelocationFactory.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/RegionFragment.h>
-#include <mcld/LD/EhFrame.h>
-#include <mcld/LD/EhFrameHdr.h>
-#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/Target/TargetLDBackend.h>
-
-using namespace mcld;
-
-/// Constructor
-MCLinker::MCLinker(TargetLDBackend& pBackend,
- MCLDInfo& pInfo,
- SectionMap& pSectionMap)
-: m_Backend(pBackend),
- m_LDInfo(pInfo),
- m_SectionMap(pSectionMap),
- m_LDSymbolFactory(128),
- m_LDSectHdrFactory(10), // the average number of sections. (assuming 10.)
- m_LDSectDataFactory(10),
- m_pSectionMerger(NULL)
-{
-}
-
-/// Destructor
-MCLinker::~MCLinker()
-{
- if (NULL != m_pSectionMerger)
- delete m_pSectionMerger;
-}
-
-//===----------------------------------------------------------------------===//
-// Symbol Operations
-//===----------------------------------------------------------------------===//
-/// addSymbolFromObject - add a symbol from object file and resolve it
-/// immediately
-LDSymbol* MCLinker::addSymbolFromObject(const llvm::StringRef& pName,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility)
-{
-
- // resolved_result is a triple <resolved_info, existent, override>
- Resolver::Result resolved_result;
- ResolveInfo old_info; // used for arrange output symbols
-
- if (pBinding == ResolveInfo::Local) {
- // if the symbol is a local symbol, create a LDSymbol for input, but do not
- // resolve them.
- resolved_result.info = m_LDInfo.getNamePool().createSymbol(pName,
- false,
- pType,
- pDesc,
- pBinding,
- pSize,
- pVisibility);
-
- // No matter if there is a symbol with the same name, insert the symbol
- // into output symbol table. So, we let the existent false.
- resolved_result.existent = false;
- resolved_result.overriden = true;
- }
- else {
- // if the symbol is not local, insert and resolve it immediately
- m_LDInfo.getNamePool().insertSymbol(pName, false, pType, pDesc, pBinding,
- pSize, pVisibility,
- &old_info, resolved_result);
- }
-
- // the return ResolveInfo should not NULL
- assert(NULL != resolved_result.info);
-
- // create a LDSymbol for the input file.
- LDSymbol* input_sym = m_LDSymbolFactory.allocate();
- new (input_sym) LDSymbol();
-
- // set the relation between input LDSymbol and its ResolveInfo
- input_sym->setResolveInfo(*resolved_result.info);
-
- // set up input LDSymbol
- input_sym->setFragmentRef(pFragmentRef);
- input_sym->setValue(pValue);
-
- LDSymbol* output_sym = resolved_result.info->outSymbol();
- bool has_output_sym = (NULL != output_sym);
- if (!resolved_result.existent || !has_output_sym) {
- // it is a new symbol, the output_sym should be NULL.
- assert(NULL == output_sym);
-
- // if it is a new symbol, create a LDSymbol for the output
- output_sym = m_LDSymbolFactory.allocate();
- new (output_sym) LDSymbol();
-
- // set up the relation between output LDSymbol and its ResolveInfo
- output_sym->setResolveInfo(*resolved_result.info);
- resolved_result.info->setSymPtr(output_sym);
- }
-
- if (resolved_result.overriden || !has_output_sym) {
- // symbol can be overriden only if it exists.
- assert(output_sym != NULL);
-
- // should override output LDSymbol
- output_sym->setFragmentRef(pFragmentRef);
- output_sym->setValue(pValue);
- }
-
- // After symbol resolution, visibility is changed to the most restrict one.
- // we need to arrange its position in the output symbol .
- if (pType != ResolveInfo::Section) {
- if (!has_output_sym) {
- // We merge sections when reading them. So we do not need to output symbols
- // with section type
-
- // No matter the symbol is already in the output or not, add it if it
- // should be forcefully set local.
- if (shouldForceLocal(*resolved_result.info))
- m_OutputSymbols.forceLocal(*output_sym);
- else {
- // the symbol should not be forcefully local.
- m_OutputSymbols.add(*output_sym);
- }
- }
- else if (resolved_result.overriden) {
- if (!shouldForceLocal(old_info) ||
- !shouldForceLocal(*resolved_result.info)) {
- // If the old info and the new info are both forcefully local, then
- // we should keep the output_sym in forcefully local category. Else,
- // we should re-sort the output_sym
- m_OutputSymbols.arrange(*output_sym, old_info);
- }
- }
- }
-
- return input_sym;
-}
-
-/// addSymbolFromDynObj - add a symbol from object file and resolve it
-/// immediately
-LDSymbol* MCLinker::addSymbolFromDynObj(const llvm::StringRef& pName,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility)
-{
- // We merge sections when reading them. So we do not need symbols with
- // section type
- if (pType == ResolveInfo::Section)
- return NULL;
-
- // ignore symbols with local binding or that have internal or hidden
- // visibility
- if (pBinding == ResolveInfo::Local ||
- pVisibility == ResolveInfo::Internal ||
- pVisibility == ResolveInfo::Hidden)
- return NULL;
-
- // A protected symbol in a shared library must be treated as a
- // normal symbol when viewed from outside the shared library.
- if (pVisibility == ResolveInfo::Protected)
- pVisibility = ResolveInfo::Default;
-
- // insert symbol and resolve it immediately
- // resolved_result is a triple <resolved_info, existent, override>
- Resolver::Result resolved_result;
- m_LDInfo.getNamePool().insertSymbol(pName, true, pType, pDesc,
- pBinding, pSize, pVisibility,
- NULL, resolved_result);
-
- // the return ResolveInfo should not NULL
- assert(NULL != resolved_result.info);
-
- // create a LDSymbol for the input file.
- LDSymbol* input_sym = m_LDSymbolFactory.allocate();
- new (input_sym) LDSymbol();
-
- // set up the relation between input LDSymbol and its ResolveInfo
- input_sym->setResolveInfo(*resolved_result.info);
-
- // set up input LDSymbol
- input_sym->setFragmentRef(pFragmentRef);
- input_sym->setValue(pValue);
-
- LDSymbol* output_sym = NULL;
- if (!resolved_result.existent) {
- // we get a new symbol, leave it as NULL
- resolved_result.info->setSymPtr(NULL);
- }
- else {
- // we saw the symbol before, but the output_sym still may be NULL.
- output_sym = resolved_result.info->outSymbol();
- }
-
- if (output_sym != NULL) {
- // After symbol resolution, visibility is changed to the most restrict one.
- // If we are not doing incremental linking, then any symbol with hidden
- // or internal visibility is forcefully set as a local symbol.
- if (shouldForceLocal(*resolved_result.info)) {
- m_OutputSymbols.forceLocal(*output_sym);
- }
- }
-
- return input_sym;
-}
-
-/// defineSymbolForcefully - define an output symbol and override it immediately
-LDSymbol* MCLinker::defineSymbolForcefully(const llvm::StringRef& pName,
- bool pIsDyn,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility)
-{
- ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
- LDSymbol* output_sym = NULL;
- if (NULL == info) {
- // the symbol is not in the pool, create a new one.
- // create a ResolveInfo
- Resolver::Result result;
- m_LDInfo.getNamePool().insertSymbol(pName, pIsDyn, pType, pDesc,
- pBinding, pSize, pVisibility,
- NULL, result);
- assert(!result.existent);
-
- // create a output LDSymbol
- output_sym = m_LDSymbolFactory.allocate();
- new (output_sym) LDSymbol();
-
- output_sym->setResolveInfo(*result.info);
- result.info->setSymPtr(output_sym);
-
- if (shouldForceLocal(*result.info))
- m_OutputSymbols.forceLocal(*output_sym);
- else
- m_OutputSymbols.add(*output_sym);
- }
- else {
- // the symbol is already in the pool, override it
- ResolveInfo old_info;
- old_info.override(*info);
-
- info->setSource(pIsDyn);
- info->setType(pType);
- info->setDesc(pDesc);
- info->setBinding(pBinding);
- info->setVisibility(pVisibility);
- info->setIsSymbol(true);
- info->setSize(pSize);
-
- output_sym = info->outSymbol();
- if (NULL != output_sym)
- m_OutputSymbols.arrange(*output_sym, old_info);
- else {
- // create a output LDSymbol
- output_sym = m_LDSymbolFactory.allocate();
- new (output_sym) LDSymbol();
-
- output_sym->setResolveInfo(*info);
- info->setSymPtr(output_sym);
-
- m_OutputSymbols.add(*output_sym);
- }
- }
-
- if (NULL != output_sym) {
- output_sym->setFragmentRef(pFragmentRef);
- output_sym->setValue(pValue);
- }
-
- return output_sym;
-}
-
-/// defineSymbolAsRefered - define an output symbol and override it immediately
-LDSymbol* MCLinker::defineSymbolAsRefered(const llvm::StringRef& pName,
- bool pIsDyn,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility)
-{
- ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
-
- if (NULL == info || !(info->isUndef() || info->isDyn())) {
- // only undefined symbol and dynamic symbol can make a reference.
- return NULL;
- }
-
- // the symbol is already in the pool, override it
- ResolveInfo old_info;
- old_info.override(*info);
-
- info->setSource(pIsDyn);
- info->setType(pType);
- info->setDesc(pDesc);
- info->setBinding(pBinding);
- info->setVisibility(pVisibility);
- info->setIsSymbol(true);
- info->setSize(pSize);
-
- LDSymbol* output_sym = info->outSymbol();
- if (NULL != output_sym) {
- output_sym->setFragmentRef(pFragmentRef);
- output_sym->setValue(pValue);
- m_OutputSymbols.arrange(*output_sym, old_info);
- }
- else {
- // create a output LDSymbol
- output_sym = m_LDSymbolFactory.allocate();
- new (output_sym) LDSymbol();
-
- output_sym->setResolveInfo(*info);
- info->setSymPtr(output_sym);
-
- m_OutputSymbols.add(*output_sym);
- }
-
- return output_sym;
-}
-
-/// defineAndResolveSymbolForcefully - define an output symbol and resolve it
-/// immediately
-LDSymbol* MCLinker::defineAndResolveSymbolForcefully(const llvm::StringRef& pName,
- bool pIsDyn,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility)
-{
- // Result is <info, existent, override>
- Resolver::Result result;
- ResolveInfo old_info;
- m_LDInfo.getNamePool().insertSymbol(pName, pIsDyn, pType, pDesc, pBinding,
- pSize, pVisibility,
- &old_info, result);
-
- LDSymbol* output_sym = result.info->outSymbol();
- bool has_output_sym = (NULL != output_sym);
-
- if (!result.existent || !has_output_sym) {
- output_sym = m_LDSymbolFactory.allocate();
- new (output_sym) LDSymbol();
- output_sym->setResolveInfo(*result.info);
- result.info->setSymPtr(output_sym);
- }
-
- if (result.overriden || !has_output_sym) {
- output_sym->setFragmentRef(pFragmentRef);
- output_sym->setValue(pValue);
- }
-
- // After symbol resolution, the visibility is changed to the most restrict.
- // arrange the output position
- if (shouldForceLocal(*result.info))
- m_OutputSymbols.forceLocal(*output_sym);
- else if (has_output_sym)
- m_OutputSymbols.arrange(*output_sym, old_info);
- else
- m_OutputSymbols.add(*output_sym);
-
- return output_sym;
-}
-
-/// defineAndResolveSymbolAsRefered - define an output symbol and resolve it
-/// immediately.
-LDSymbol* MCLinker::defineAndResolveSymbolAsRefered(const llvm::StringRef& pName,
- bool pIsDyn,
- ResolveInfo::Type pType,
- ResolveInfo::Desc pDesc,
- ResolveInfo::Binding pBinding,
- ResolveInfo::SizeType pSize,
- LDSymbol::ValueType pValue,
- FragmentRef* pFragmentRef,
- ResolveInfo::Visibility pVisibility)
-{
- ResolveInfo* info = m_LDInfo.getNamePool().findInfo(pName);
-
- if (NULL == info || !(info->isUndef() || info->isDyn())) {
- // only undefined symbol and dynamic symbol can make a reference.
- return NULL;
- }
-
- return defineAndResolveSymbolForcefully(pName,
- pIsDyn,
- pType,
- pDesc,
- pBinding,
- pSize,
- pValue,
- pFragmentRef,
- pVisibility);
-}
-
-bool MCLinker::finalizeSymbols()
-{
- SymbolCategory::iterator symbol, symEnd = m_OutputSymbols.end();
- for (symbol = m_OutputSymbols.begin(); symbol != symEnd; ++symbol) {
-
- if ((*symbol)->resolveInfo()->isAbsolute() ||
- (*symbol)->resolveInfo()->type() == ResolveInfo::File) {
- // absolute symbols or symbols with function type should have
- // zero value
- (*symbol)->setValue(0x0);
- continue;
- }
-
- if ((*symbol)->hasFragRef()) {
- // set the virtual address of the symbol. If the output file is
- // relocatable object file, the section's virtual address becomes zero.
- // And the symbol's value become section relative offset.
- uint64_t value = getLayout().getOutputOffset(*(*symbol)->fragRef());
- assert(NULL != (*symbol)->fragRef()->frag());
- uint64_t addr = getLayout().getOutputLDSection(*(*symbol)->fragRef()->frag())->addr();
- (*symbol)->setValue(value + addr);
- continue;
- }
- }
-
- // finialize target-dependent symbols
- return m_Backend.finalizeSymbols(*this, m_LDInfo.output());
-}
-
-bool MCLinker::shouldForceLocal(const ResolveInfo& pInfo) const
-{
- // forced local symbol matches all rules:
- // 1. We are not doing incremental linking.
- // 2. The symbol is with Hidden or Internal visibility.
- // 3. The symbol should be global or weak. Otherwise, local symbol is local.
- // 4. The symbol is defined or common
- if (m_LDInfo.output().type() != Output::Object &&
- (pInfo.visibility() == ResolveInfo::Hidden ||
- pInfo.visibility() == ResolveInfo::Internal) &&
- (pInfo.isGlobal() || pInfo.isWeak()) &&
- (pInfo.isDefine() || pInfo.isCommon()))
- return true;
- return false;
-}
-
-//===----------------------------------------------------------------------===//
-// Section Operations
-//===----------------------------------------------------------------------===//
-/// createSectHdr - create the input section header
-LDSection& MCLinker::createSectHdr(const std::string& pName,
- LDFileFormat::Kind pKind,
- uint32_t pType,
- uint32_t pFlag)
-{
- assert(m_LDInfo.output().hasContext());
-
- // for user such as reader, standard/target fromat
- LDSection* result =
- m_LDSectHdrFactory.produce(pName, pKind, pType, pFlag);
-
- // check if we need to create a output section for output LDContext
- std::string sect_name = m_SectionMap.getOutputSectName(pName);
- LDSection* output_sect = m_LDInfo.output().context()->getSection(sect_name);
-
- if (NULL == output_sect) {
- // create a output section and push it into output LDContext
- output_sect =
- m_LDSectHdrFactory.produce(sect_name, pKind, pType, pFlag);
- m_LDInfo.output().context()->getSectionTable().push_back(output_sect);
- m_pSectionMerger->addMapping(pName, output_sect);
- }
- return *result;
-}
-
-/// getOrCreateOutputSectHdr - for reader and standard/target format to get
-/// or create the output's section header
-LDSection& MCLinker::getOrCreateOutputSectHdr(const std::string& pName,
- LDFileFormat::Kind pKind,
- uint32_t pType,
- uint32_t pFlag,
- uint32_t pAlign)
-{
- assert(m_LDInfo.output().hasContext());
-
- // check if we need to create a output section for output LDContext
- std::string sect_name = m_SectionMap.getOutputSectName(pName);
- LDSection* output_sect = m_LDInfo.output().context()->getSection(sect_name);
-
- if (NULL == output_sect) {
- // create a output section and push it into output LDContext
- output_sect =
- m_LDSectHdrFactory.produce(sect_name, pKind, pType, pFlag);
- output_sect->setAlign(pAlign);
- m_LDInfo.output().context()->getSectionTable().push_back(output_sect);
- m_pSectionMerger->addMapping(pName, output_sect);
- }
- return *output_sect;
-}
-
-/// getOrCreateSectData - get or create SectionData
-/// pSection is input LDSection
-SectionData& MCLinker::getOrCreateSectData(LDSection& pSection)
-{
- // if there is already a section data pointed by section, return it.
- SectionData* sect_data = pSection.getSectionData();
- if (NULL != sect_data) {
- m_Layout.addInputRange(*sect_data, pSection);
- return *sect_data;
- }
-
- // try to get one from output LDSection
- LDSection* output_sect =
- m_pSectionMerger->getOutputSectHdr(pSection.name());
-
- assert(NULL != output_sect);
-
- sect_data = output_sect->getSectionData();
-
- if (NULL != sect_data) {
- pSection.setSectionData(sect_data);
- m_Layout.addInputRange(*sect_data, pSection);
- return *sect_data;
- }
-
- // if the output LDSection also has no SectionData, then create one.
- sect_data = m_LDSectDataFactory.allocate();
- new (sect_data) SectionData(*output_sect);
- pSection.setSectionData(sect_data);
- output_sect->setSectionData(sect_data);
- m_Layout.addInputRange(*sect_data, pSection);
- return *sect_data;
-}
-
-void MCLinker::initSectionMap()
-{
- assert(m_LDInfo.output().hasContext());
- if (NULL == m_pSectionMerger)
- m_pSectionMerger = new SectionMerger(m_SectionMap, *m_LDInfo.output().context());
-}
-
-bool MCLinker::layout()
-{
- return m_Layout.layout(m_LDInfo.output(), m_Backend, m_LDInfo);
-}
-
-//===----------------------------------------------------------------------===//
-// Relocation Operations
-//===----------------------------------------------------------------------===//
-/// addRelocation - add a relocation entry in MCLinker (only for object file)
-///
-/// All symbols should be read and resolved before calling this function.
-Relocation* MCLinker::addRelocation(Relocation::Type pType,
- const LDSymbol& pSym,
- ResolveInfo& pResolveInfo,
- FragmentRef& pFragmentRef,
- const LDSection& pSection,
- Relocation::Address pAddend)
-{
- // FIXME: we should dicard sections and symbols first instead
- // if the symbol is in the discarded input section, then we also need to
- // discard this relocation.
- if (pSym.fragRef() == NULL &&
- pResolveInfo.type() == ResolveInfo::Section &&
- pResolveInfo.desc() == ResolveInfo::Undefined)
- return NULL;
-
- Relocation* relocation = m_Backend.getRelocFactory()->produce(pType,
- pFragmentRef,
- pAddend);
-
- relocation->setSymInfo(&pResolveInfo);
-
- m_RelocationList.push_back(relocation);
-
- m_Backend.scanRelocation(*relocation, pSym, *this, m_LDInfo,
- m_LDInfo.output(), pSection);
-
- if (pResolveInfo.isUndef() && !pResolveInfo.isDyn() && !pResolveInfo.isWeak())
- fatal(diag::undefined_reference) << pResolveInfo.name();
- return relocation;
-}
-
-bool MCLinker::applyRelocations()
-{
- RelocationListType::iterator relocIter, relocEnd = m_RelocationList.end();
-
- for (relocIter = m_RelocationList.begin(); relocIter != relocEnd; ++relocIter) {
- Fragment* frag = (Fragment*)relocIter;
- static_cast<Relocation*>(frag)->apply(*m_Backend.getRelocFactory(), m_LDInfo);
- }
- return true;
-}
-
-void MCLinker::syncRelocationResult()
-{
-
- MemoryRegion* region = m_LDInfo.output().memArea()->request(0,
- m_LDInfo.output().memArea()->handler()->size());
-
- uint8_t* data = region->getBuffer();
-
- RelocationListType::iterator relocIter, relocEnd = m_RelocationList.end();
- for (relocIter = m_RelocationList.begin(); relocIter != relocEnd; ++relocIter) {
-
- Fragment* frag = (Fragment*)relocIter;
- Relocation* reloc = static_cast<Relocation*>(frag);
-
- // get output file offset
- size_t out_offset = m_Layout.getOutputLDSection(*reloc->targetRef().frag())->offset() +
- m_Layout.getOutputOffset(reloc->targetRef());
-
- uint8_t* target_addr = data + out_offset;
- // byte swapping if target and host has different endian, and then write back
- if(llvm::sys::isLittleEndianHost() != m_Backend.isLittleEndian()) {
- uint64_t tmp_data = 0;
-
- switch(m_Backend.bitclass()) {
- case 32u:
- tmp_data = bswap32(reloc->target());
- std::memcpy(target_addr, &tmp_data, 4);
- break;
-
- case 64u:
- tmp_data = bswap64(reloc->target());
- std::memcpy(target_addr, &tmp_data, 8);
- break;
-
- default:
- break;
- }
- }
- else {
- std::memcpy(target_addr, &reloc->target(), m_Backend.bitclass()/8);
- }
- } // end of for
-
- m_LDInfo.output().memArea()->clear();
-}
-
-//===----------------------------------------------------------------------===//
-// Exception Handling Operations
-//===----------------------------------------------------------------------===//
-/// addEhFrame - add an exception handling section
-/// @param pSection - the input section
-/// @param pArea - the memory area which pSection is within.
-uint64_t MCLinker::addEhFrame(const Input& pInput,
- LDSection& pSection,
- MemoryArea& pArea)
-{
- uint64_t size = 0;
-
- // get the SectionData of this eh_frame
- SectionData& sect_data = getOrCreateSectData(pSection);
-
- // parse the eh_frame if the option --eh-frame-hdr is given
- if (m_LDInfo.options().hasEhFrameHdr()) {
- EhFrame* ehframe = m_Backend.getEhFrame();
- assert(NULL != ehframe);
- if (ehframe->canRecognizeAllEhFrame()) {
- size = ehframe->readEhFrame(m_Layout, m_Backend, sect_data, pInput,
- pSection, pArea);
- // zero size indicate that this is an empty section or we can't recognize
- // this eh_frame, handle it as a regular section.
- if (0 != size)
- return size;
- }
- }
-
- // handle eh_frame as a regular section
- MemoryRegion* region = pArea.request(pInput.fileOffset() + pSection.offset(),
- pSection.size());
-
- Fragment* frag = NULL;
- if (NULL == region) {
- // If the input section's size is zero, we got a NULL region.
- // use a virtual fill fragment
- frag = new FillFragment(0x0, 0, 0);
- }
- else
- frag = new RegionFragment(*region);
-
- size = m_Layout.appendFragment(*frag, sect_data, pSection.align());
- return size;
-}
-
diff --git a/lib/MC/SearchDirs.cpp b/lib/MC/SearchDirs.cpp
index 40d625b..12d08e2 100644
--- a/lib/MC/SearchDirs.cpp
+++ b/lib/MC/SearchDirs.cpp
@@ -14,7 +14,8 @@
//===----------------------------------------------------------------------===//
// Non-member functions
-static void SpecToFilename(const std::string& pSpec, std::string& pFile)
+//===----------------------------------------------------------------------===//
+static inline void SpecToFilename(const std::string& pSpec, std::string& pFile)
{
pFile = "lib";
pFile += pSpec;
@@ -22,6 +23,7 @@
//===----------------------------------------------------------------------===//
// SearchDirs
+//===----------------------------------------------------------------------===//
SearchDirs::SearchDirs()
{
// a magic number 8, no why.
@@ -29,6 +31,13 @@
m_DirList.reserve(8);
}
+SearchDirs::SearchDirs(const sys::fs::Path& pSysRoot)
+ : m_SysRoot(pSysRoot) {
+ // a magic number 8, no why.
+ // please prove it or change it
+ m_DirList.reserve(8);
+}
+
SearchDirs::~SearchDirs()
{
iterator dir, dirEnd = end();
@@ -37,9 +46,22 @@
}
}
-void SearchDirs::add(const MCLDDirectory& pDirectory)
+bool SearchDirs::insert(const std::string& pPath)
{
- m_DirList.push_back(new MCLDDirectory(pDirectory));
+ MCLDDirectory* dir = new MCLDDirectory(pPath);
+ if (dir->isInSysroot())
+ dir->setSysroot(m_SysRoot);
+
+ if (exists(dir->path()) && is_directory(dir->path())) {
+ m_DirList.push_back(dir);
+ return true;
+ }
+ return false;
+}
+
+bool SearchDirs::insert(const sys::fs::Path& pPath)
+{
+ return insert(pPath.native());
}
mcld::sys::fs::Path* SearchDirs::find(const std::string& pNamespec, mcld::Input::Type pType)
@@ -85,3 +107,46 @@
return NULL;
}
+const mcld::sys::fs::Path*
+SearchDirs::find(const std::string& pNamespec, mcld::Input::Type pType) const
+{
+ assert(Input::DynObj == pType || Input::Archive == pType);
+
+ std::string file;
+ SpecToFilename(pNamespec, file);
+ // for all MCLDDirectorys
+ DirList::const_iterator mcld_dir, mcld_dir_end = m_DirList.end();
+ for (mcld_dir=m_DirList.begin(); mcld_dir!=mcld_dir_end; ++mcld_dir) {
+ // for all entries in MCLDDirectory
+ MCLDDirectory::iterator entry = (*mcld_dir)->begin();
+ MCLDDirectory::iterator enEnd = (*mcld_dir)->end();
+
+ switch(pType) {
+ case Input::DynObj: {
+ while (entry!=enEnd) {
+ if (file == entry.path()->stem().native() ) {
+ if(mcld::sys::fs::detail::shared_library_extension == entry.path()->extension().native()) {
+ return entry.path();
+ }
+ }
+ ++entry;
+ }
+ }
+ /** Fall through **/
+ case Input::Archive : {
+ entry = (*mcld_dir)->begin();
+ enEnd = (*mcld_dir)->end();
+ while ( entry!=enEnd ) {
+ if (file == entry.path()->stem().native() &&
+ mcld::sys::fs::detail::static_library_extension == entry.path()->extension().native()) {
+ return entry.path();
+ }
+ ++entry;
+ }
+ }
+ default:
+ break;
+ } // end of switch
+ } // end of while
+ return NULL;
+}
diff --git a/lib/MC/SymbolCategory.cpp b/lib/MC/SymbolCategory.cpp
index 4b5e0f7..f01083f 100644
--- a/lib/MC/SymbolCategory.cpp
+++ b/lib/MC/SymbolCategory.cpp
@@ -35,19 +35,22 @@
{
m_pFile = new Category(Category::File);
m_pLocal = new Category(Category::Local);
+ m_pTLS = new Category(Category::TLS);
m_pCommon = new Category(Category::Common);
m_pWeak = new Category(Category::Weak);
m_pGlobal = new Category(Category::Global);
m_pFile->next = m_pLocal;
- m_pLocal->next = m_pCommon;
+ m_pLocal->next = m_pTLS;
+ m_pTLS->next = m_pCommon;
m_pCommon->next = m_pWeak;
m_pWeak->next = m_pGlobal;
m_pGlobal->prev = m_pWeak;
m_pWeak->prev = m_pCommon;
- m_pCommon->prev = m_pLocal;
- m_pLocal->prev = m_pFile;
+ m_pCommon->prev = m_pTLS;
+ m_pTLS->prev = m_pLocal;
+ m_pLocal->prev = m_pFile;
}
SymbolCategory::~SymbolCategory()
@@ -92,6 +95,8 @@
{
m_OutputSymbols.insert(localEnd(), &pSymbol);
m_pLocal->end++;
+ m_pTLS->begin++;
+ m_pTLS->end++;
m_pCommon->begin++;
m_pCommon->end++;
m_pWeak->begin++;
@@ -203,6 +208,27 @@
return *this;
}
+SymbolCategory& SymbolCategory::changeLocalToTLS(const LDSymbol& pSymbol)
+{
+ // find the position of pSymbol from local category
+ size_t pos = m_pLocal->begin;
+ while (pos != m_pLocal->end) {
+ if (m_OutputSymbols[pos] == &pSymbol)
+ break;
+ ++pos;
+ }
+
+ // if symbol is not in Local, then do nothing
+ if (m_pLocal->end == pos)
+ return *this;
+
+ // bubble sort downward to TLS
+ std::swap(m_OutputSymbols[pos], m_OutputSymbols[m_pLocal->end - 1]);
+ m_pLocal->end--;
+ m_pTLS->begin--;
+ return *this;
+}
+
size_t SymbolCategory::numOfSymbols() const
{
return m_OutputSymbols.size();
@@ -210,7 +236,7 @@
size_t SymbolCategory::numOfLocals() const
{
- return (m_pFile->size() + m_pLocal->size());
+ return (m_pFile->size() + m_pLocal->size() + m_pTLS->size());
}
size_t SymbolCategory::numOfCommons() const
@@ -232,7 +258,7 @@
bool SymbolCategory::emptyLocals() const
{
- return (m_pFile->empty() && m_pLocal->empty());
+ return (m_pFile->empty() && m_pLocal->empty() && m_pTLS->empty());
}
bool SymbolCategory::emptyCommons() const
@@ -291,26 +317,50 @@
return iter;
}
-SymbolCategory::iterator SymbolCategory::commonBegin()
+SymbolCategory::iterator SymbolCategory::tlsBegin()
{
return localEnd();
}
-SymbolCategory::iterator SymbolCategory::commonEnd()
+SymbolCategory::iterator SymbolCategory::tlsEnd()
{
iterator iter = localEnd();
+ iter += m_pTLS->size();
+ return iter;
+}
+
+SymbolCategory::const_iterator SymbolCategory::tlsBegin() const
+{
+ return localEnd();
+}
+
+SymbolCategory::const_iterator SymbolCategory::tlsEnd() const
+{
+ const_iterator iter = localEnd();
+ iter += m_pTLS->size();
+ return iter;
+}
+
+SymbolCategory::iterator SymbolCategory::commonBegin()
+{
+ return tlsEnd();
+}
+
+SymbolCategory::iterator SymbolCategory::commonEnd()
+{
+ iterator iter = tlsEnd();
iter += m_pCommon->size();
return iter;
}
SymbolCategory::const_iterator SymbolCategory::commonBegin() const
{
- return localEnd();
+ return tlsEnd();
}
SymbolCategory::const_iterator SymbolCategory::commonEnd() const
{
- const_iterator iter = localEnd();
+ const_iterator iter = tlsEnd();
iter += m_pCommon->size();
return iter;
}
diff --git a/lib/Object/Android.mk b/lib/Object/Android.mk
new file mode 100644
index 0000000..56334f9
--- /dev/null
+++ b/lib/Object/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH:= $(call my-dir)
+
+mcld_object_SRC_FILES := \
+ ObjectBuilder.cpp \
+ ObjectLinker.cpp \
+ SectionMap.cpp
+
+# For the host
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_object_SRC_FILES)
+LOCAL_MODULE:= libmcldObject
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_HOST_BUILD_MK)
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+# For the device
+# =====================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(mcld_object_SRC_FILES)
+LOCAL_MODULE:= libmcldObject
+
+LOCAL_MODULE_TAGS := optional
+
+include $(MCLD_DEVICE_BUILD_MK)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/lib/Object/ObjectBuilder.cpp b/lib/Object/ObjectBuilder.cpp
new file mode 100644
index 0000000..ec09901
--- /dev/null
+++ b/lib/Object/ObjectBuilder.cpp
@@ -0,0 +1,181 @@
+//===- ObjectBuilder.cpp --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Object/ObjectBuilder.h>
+
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/Object/SectionMap.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/SectionData.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/Fragment/Relocation.h>
+#include <mcld/Fragment/AlignFragment.h>
+#include <mcld/Fragment/NullFragment.h>
+#include <mcld/Fragment/FillFragment.h>
+
+#include <llvm/Support/Casting.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ObjectBuilder
+//===----------------------------------------------------------------------===//
+ObjectBuilder::ObjectBuilder(const LinkerConfig& pConfig, Module& pTheModule)
+ : m_Config(pConfig), m_Module(pTheModule) {
+}
+
+/// CreateSection - create an output section.
+LDSection* ObjectBuilder::CreateSection(const std::string& pName,
+ LDFileFormat::Kind pKind,
+ uint32_t pType,
+ uint32_t pFlag,
+ uint32_t pAlign)
+{
+ // try to get one from output LDSection
+ const SectionMap::NamePair& pair = m_Config.scripts().sectionMap().find(pName);
+ std::string output_name = (pair.isNull())?pName:pair.to;
+ LDSection* output_sect = LDSection::Create(output_name, pKind, pType, pFlag);
+ output_sect->setAlign(pAlign);
+ m_Module.getSectionTable().push_back(output_sect);
+ return output_sect;
+}
+
+/// MergeSection - merge the pInput section to the pOutput section
+bool ObjectBuilder::MergeSection(LDSection& pInputSection)
+{
+ const SectionMap::NamePair& pair =
+ m_Config.scripts().sectionMap().find(pInputSection.name());
+ std::string output_name = (pair.isNull())?pInputSection.name():pair.to;
+ LDSection* target = m_Module.getSection(output_name);
+
+ if (NULL == target) {
+ target = LDSection::Create(output_name,
+ pInputSection.kind(),
+ pInputSection.type(),
+ pInputSection.flag());
+ target->setAlign(pInputSection.align());
+ m_Module.getSectionTable().push_back(target);
+ }
+
+ switch (target->kind()) {
+ // Some *OUTPUT sections should not be merged.
+ case LDFileFormat::Relocation:
+ case LDFileFormat::NamePool:
+ /** do nothing **/
+ return true;
+ case LDFileFormat::EhFrame: {
+ EhFrame* eh_frame = NULL;
+ if (target->hasEhFrame())
+ eh_frame = target->getEhFrame();
+ else
+ eh_frame = IRBuilder::CreateEhFrame(*target);
+
+ eh_frame->merge(*pInputSection.getEhFrame());
+ return true;
+ }
+ default: {
+ SectionData* data = NULL;
+ if (target->hasSectionData())
+ data = target->getSectionData();
+ else
+ data = IRBuilder::CreateSectionData(*target);
+
+ return MoveSectionData(*pInputSection.getSectionData(), *data);
+ }
+ }
+ return true;
+}
+
+/// MoveSectionData - move the fragments of pTO section data to pTo
+bool ObjectBuilder::MoveSectionData(SectionData& pFrom, SectionData& pTo)
+{
+ assert(&pFrom != &pTo && "Cannot move section data to itself!");
+
+ uint32_t offset = pTo.getSection().size();
+ AlignFragment* align = NULL;
+ if (pFrom.getSection().align() > 1) {
+ // if the align constraint is larger than 1, append an alignment
+ align = new AlignFragment(pFrom.getSection().align(), // alignment
+ 0x0, // the filled value
+ 1u, // the size of filled value
+ pFrom.getSection().align() - 1 // max bytes to emit
+ );
+ align->setOffset(offset);
+ align->setParent(&pTo);
+ pTo.getFragmentList().push_back(align);
+ offset += align->size();
+ }
+
+ // move fragments from pFrom to pTO
+ SectionData::FragmentListType& from_list = pFrom.getFragmentList();
+ SectionData::FragmentListType& to_list = pTo.getFragmentList();
+ SectionData::FragmentListType::iterator frag, fragEnd = from_list.end();
+ for (frag = from_list.begin(); frag != fragEnd; ++frag) {
+ frag->setParent(&pTo);
+ frag->setOffset(offset);
+ offset += frag->size();
+ }
+ to_list.splice(to_list.end(), from_list);
+
+ // append the null fragment
+ NullFragment* null = new NullFragment();
+ null->setParent(&pTo);
+ null->setOffset(offset);
+ pTo.getFragmentList().push_back(null);
+
+ // set up pTo's header
+ pTo.getSection().setSize(offset);
+ if (pFrom.getSection().align() > pTo.getSection().align())
+ pTo.getSection().setAlign(pFrom.getSection().align());
+
+ return true;
+}
+
+/// AppendFragment - To append pFrag to the given SectionData pSD.
+uint64_t ObjectBuilder::AppendFragment(Fragment& pFrag,
+ SectionData& pSD,
+ uint32_t pAlignConstraint)
+{
+ // get initial offset.
+ uint32_t offset = 0;
+ if (!pSD.empty())
+ offset = pSD.back().getOffset() + pSD.back().size();
+
+ AlignFragment* align = NULL;
+ if (pAlignConstraint > 1) {
+ // if the align constraint is larger than 1, append an alignment
+ align = new AlignFragment(pAlignConstraint, // alignment
+ 0x0, // the filled value
+ 1u, // the size of filled value
+ pAlignConstraint - 1 // max bytes to emit
+ );
+ align->setOffset(offset);
+ align->setParent(&pSD);
+ pSD.getFragmentList().push_back(align);
+ offset += align->size();
+ }
+
+ // append the fragment
+ pFrag.setParent(&pSD);
+ pFrag.setOffset(offset);
+ pSD.getFragmentList().push_back(&pFrag);
+
+ // append the null fragment
+ offset += pFrag.size();
+ NullFragment* null = new NullFragment(&pSD);
+ null->setOffset(offset);
+
+ if (NULL != align)
+ return align->size() + pFrag.size();
+ else
+ return pFrag.size();
+}
+
diff --git a/lib/Object/ObjectLinker.cpp b/lib/Object/ObjectLinker.cpp
new file mode 100644
index 0000000..93fdb20
--- /dev/null
+++ b/lib/Object/ObjectLinker.cpp
@@ -0,0 +1,442 @@
+//===- ObjectLinker.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Object/ObjectLinker.h>
+
+#include <mcld/LinkerConfig.h>
+#include <mcld/Module.h>
+#include <mcld/InputTree.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LD/LDContext.h>
+#include <mcld/LD/Archive.h>
+#include <mcld/LD/ArchiveReader.h>
+#include <mcld/LD/ObjectReader.h>
+#include <mcld/LD/DynObjReader.h>
+#include <mcld/LD/GroupReader.h>
+#include <mcld/LD/ObjectWriter.h>
+#include <mcld/LD/DynObjWriter.h>
+#include <mcld/LD/ExecWriter.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/Layout.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/Support/RealPath.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Target/TargetLDBackend.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/Object/ObjectBuilder.h>
+
+#include <llvm/Support/Casting.h>
+
+using namespace llvm;
+using namespace mcld;
+
+ObjectLinker::ObjectLinker(const LinkerConfig& pConfig,
+ Module& pModule,
+ InputBuilder& pInputBuilder,
+ TargetLDBackend& pLDBackend)
+ : m_Config(pConfig),
+ m_Module(pModule),
+ m_InputBuilder(pInputBuilder),
+ m_pLinker(NULL),
+ m_LDBackend(pLDBackend),
+ m_pObjectReader(NULL),
+ m_pDynObjReader(NULL),
+ m_pArchiveReader(NULL),
+ m_pObjectWriter(NULL),
+ m_pDynObjWriter(NULL),
+ m_pExecWriter(NULL),
+ m_pGroupReader(NULL)
+{
+ // set up soname
+ if (!m_Config.options().soname().empty()) {
+ m_Module.setName(m_Config.options().soname());
+ }
+}
+
+ObjectLinker::~ObjectLinker()
+{
+ delete m_pLinker;
+ delete m_pObjectReader;
+ delete m_pDynObjReader;
+ delete m_pArchiveReader;
+ delete m_pObjectWriter;
+ delete m_pDynObjWriter;
+ delete m_pExecWriter;
+ delete m_pGroupReader;
+}
+
+/// initFragmentLinker - initialize FragmentLinker
+/// Connect all components with FragmentLinker
+bool ObjectLinker::initFragmentLinker()
+{
+ if (NULL == m_pLinker) {
+ m_pLinker = new FragmentLinker(m_Config,
+ m_Module,
+ m_LDBackend);
+ }
+
+ // initialize the readers and writers
+ // Because constructor can not be failed, we initalize all readers and
+ // writers outside the FragmentLinker constructors.
+ m_pObjectReader = m_LDBackend.createObjectReader(*m_pLinker);
+ m_pArchiveReader = m_LDBackend.createArchiveReader(m_Module);
+ m_pDynObjReader = m_LDBackend.createDynObjReader(*m_pLinker);
+ m_pObjectWriter = m_LDBackend.createObjectWriter(*m_pLinker);
+ m_pDynObjWriter = m_LDBackend.createDynObjWriter(*m_pLinker);
+ m_pExecWriter = m_LDBackend.createExecWriter(*m_pLinker);
+ m_pGroupReader = new GroupReader(m_Module, *m_pObjectReader,
+ *m_pDynObjReader, *m_pArchiveReader);
+
+ // initialize RelocationFactory
+ m_LDBackend.initRelocFactory(*m_pLinker);
+
+ // initialize BranchIslandFactory
+ m_LDBackend.initBRIslandFactory();
+
+ // initialize StubFactory
+ m_LDBackend.initStubFactory();
+
+ // initialize target stubs
+ m_LDBackend.initTargetStubs(*m_pLinker);
+ return true;
+}
+
+/// initStdSections - initialize standard sections
+bool ObjectLinker::initStdSections()
+{
+ ObjectBuilder builder(m_Config, m_Module);
+
+ // initialize standard sections
+ if (!m_LDBackend.initStdSections(builder))
+ return false;
+
+ // initialize target-dependent sections
+ m_LDBackend.initTargetSections(m_Module, builder);
+
+ return true;
+}
+
+void ObjectLinker::normalize()
+{
+ // ----- set up inputs ----- //
+ Module::input_iterator input, inEnd = m_Module.input_end();
+ for (input = m_Module.input_begin(); input!=inEnd; ++input) {
+ // is a group node
+ if (isGroup(input)) {
+ getGroupReader()->readGroup(input, m_InputBuilder, m_Config);
+ continue;
+ }
+
+ // already got type - for example, bitcode or external OIR (object
+ // intermediate representation)
+ if ((*input)->type() == Input::Script ||
+ (*input)->type() == Input::Archive ||
+ (*input)->type() == Input::External)
+ continue;
+
+ if (Input::Object == (*input)->type()) {
+ m_Module.getObjectList().push_back(*input);
+ continue;
+ }
+
+ if (Input::DynObj == (*input)->type()) {
+ m_Module.getLibraryList().push_back(*input);
+ continue;
+ }
+
+ // is a relocatable object file
+ if (getObjectReader()->isMyFormat(**input)) {
+ (*input)->setType(Input::Object);
+ getObjectReader()->readHeader(**input);
+ getObjectReader()->readSections(**input);
+ getObjectReader()->readSymbols(**input);
+ m_Module.getObjectList().push_back(*input);
+ }
+ // is a shared object file
+ else if (getDynObjReader()->isMyFormat(**input)) {
+ (*input)->setType(Input::DynObj);
+ getDynObjReader()->readHeader(**input);
+ getDynObjReader()->readSymbols(**input);
+ m_Module.getLibraryList().push_back(*input);
+ }
+ // is an archive
+ else if (getArchiveReader()->isMyFormat(**input)) {
+ (*input)->setType(Input::Archive);
+ Archive archive(**input, m_InputBuilder);
+ getArchiveReader()->readArchive(archive);
+ if(archive.numOfObjectMember() > 0) {
+ m_Module.getInputTree().merge<InputTree::Inclusive>(input,
+ archive.inputs());
+ }
+ }
+ else {
+ fatal(diag::err_unrecognized_input_file) << (*input)->path()
+ << m_Config.triple().str();
+ }
+ } // end of for
+}
+
+bool ObjectLinker::linkable() const
+{
+ // check we have input and output files
+ if (m_Module.getInputTree().empty()) {
+ error(diag::err_no_inputs);
+ return false;
+ }
+
+ // can not mix -static with shared objects
+ Module::const_lib_iterator lib, libEnd = m_Module.lib_end();
+ for (lib = m_Module.lib_begin(); lib != libEnd; ++lib) {
+ if((*lib)->attribute()->isStatic()) {
+ error(diag::err_mixed_shared_static_objects)
+ << (*lib)->name() << (*lib)->path();
+ return false;
+ }
+ }
+
+ // can not mix -r with shared objects
+ return true;
+}
+
+/// readRelocations - read all relocation entries
+///
+/// All symbols should be read and resolved before this function.
+bool ObjectLinker::readRelocations()
+{
+ // Bitcode is read by the other path. This function reads relocation sections
+ // in object files.
+ mcld::InputTree::bfs_iterator input, inEnd = m_Module.getInputTree().bfs_end();
+ for (input=m_Module.getInputTree().bfs_begin(); input!=inEnd; ++input) {
+ if ((*input)->type() == Input::Object && (*input)->hasMemArea()) {
+ if (!getObjectReader()->readRelocations(**input))
+ return false;
+ }
+ // ignore the other kinds of files.
+ }
+ return true;
+}
+
+/// mergeSections - put allinput sections into output sections
+bool ObjectLinker::mergeSections()
+{
+ ObjectBuilder builder(m_Config, m_Module);
+ Module::obj_iterator obj, objEnd = m_Module.obj_end();
+ for (obj = m_Module.obj_begin(); obj != objEnd; ++obj) {
+ LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd();
+ for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) {
+ switch ((*sect)->kind()) {
+ // Some *INPUT sections should not be merged.
+ case LDFileFormat::Ignore:
+ case LDFileFormat::Null:
+ case LDFileFormat::Relocation:
+ case LDFileFormat::NamePool:
+ case LDFileFormat::Group:
+ case LDFileFormat::StackNote:
+ // skip
+ continue;
+ case LDFileFormat::Target:
+ if (!m_LDBackend.mergeSection(m_Module, **sect)) {
+ error(diag::err_cannot_merge_section) << (*sect)->name()
+ << (*obj)->name();
+ return false;
+ }
+ break;
+ case LDFileFormat::EhFrame: {
+ if (!(*sect)->hasEhFrame())
+ continue; // skip
+
+ if (!builder.MergeSection(**sect)) {
+ error(diag::err_cannot_merge_section) << (*sect)->name()
+ << (*obj)->name();
+ return false;
+ }
+ break;
+ }
+ default: {
+ if (!(*sect)->hasSectionData())
+ continue; // skip
+
+ if (!builder.MergeSection(**sect)) {
+ error(diag::err_cannot_merge_section) << (*sect)->name()
+ << (*obj)->name();
+ return false;
+ }
+ break;
+ }
+ } // end of switch
+ } // for each section
+ } // for each obj
+ return true;
+}
+
+/// addStandardSymbols - shared object and executable files need some
+/// standard symbols
+/// @return if there are some input symbols with the same name to the
+/// standard symbols, return false
+bool ObjectLinker::addStandardSymbols()
+{
+ // create and add section symbols for each output section
+ Module::iterator iter, iterEnd = m_Module.end();
+ for (iter = m_Module.begin(); iter != iterEnd; ++iter) {
+ m_Module.getSectionSymbolSet().add(**iter, m_Module.getNamePool());
+ }
+
+ return m_LDBackend.initStandardSymbols(*m_pLinker, m_Module);
+}
+
+/// addTargetSymbols - some targets, such as MIPS and ARM, need some
+/// target-dependent symbols
+/// @return if there are some input symbols with the same name to the
+/// target symbols, return false
+bool ObjectLinker::addTargetSymbols()
+{
+ m_LDBackend.initTargetSymbols(*m_pLinker);
+ return true;
+}
+
+bool ObjectLinker::scanRelocations()
+{
+ // apply all relocations of all inputs
+ Module::obj_iterator input, inEnd = m_Module.obj_end();
+ for (input = m_Module.obj_begin(); input != inEnd; ++input) {
+ LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
+ for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
+ // bypass the reloc section if
+ // 1. its section kind is changed to Ignore. (The target section is a
+ // discarded group section.)
+ // 2. it has no reloc data. (All symbols in the input relocs are in the
+ // discarded group sections)
+ if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
+ continue;
+ RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
+ for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
+ Relocation* relocation = llvm::cast<Relocation>(reloc);
+ // scan relocation
+ if (LinkerConfig::Object != m_Config.codeGenType()) {
+ m_LDBackend.scanRelocation(*relocation,
+ *m_pLinker,
+ m_Module,
+ *(*rs)->getLink());
+ }
+ else {
+ m_LDBackend.partialScanRelocation(*relocation,
+ *m_pLinker,
+ m_Module,
+ *(*rs)->getLink());
+ }
+ } // for all relocations
+ } // for all relocation section
+ } // for all inputs
+ return true;
+}
+
+/// prelayout - help backend to do some modification before layout
+bool ObjectLinker::prelayout()
+{
+ // finalize the section symbols, set their fragment reference and push them
+ // into output symbol table
+ Module::iterator iter, iterEnd = m_Module.end();
+ for (iter = m_Module.begin(); iter != iterEnd; ++iter) {
+ LDSection* section = *iter;
+ if (0x0 == section->size() || LDFileFormat::Relocation == section->kind())
+ continue;
+ m_Module.getSectionSymbolSet().finalize(
+ *section, m_Module.getSymbolTable());
+ }
+
+ m_LDBackend.preLayout(m_Module, *m_pLinker);
+
+ m_LDBackend.allocateCommonSymbols(m_Module);
+
+ /// check program interpreter - computer the name size of the runtime dyld
+ if (!m_pLinker->isStaticLink() &&
+ (LinkerConfig::Exec == m_Config.codeGenType() ||
+ m_Config.options().isPIE() ||
+ m_Config.options().hasDyld()))
+ m_LDBackend.sizeInterp();
+
+ /// measure NamePools - compute the size of name pool sections
+ /// In ELF, will compute the size of.symtab, .strtab, .dynsym, .dynstr,
+ /// .hash and .shstrtab sections.
+ ///
+ /// dump all symbols and strings from FragmentLinker and build the format-dependent
+ /// hash table.
+ m_LDBackend.sizeNamePools(m_Module, m_pLinker->isStaticLink());
+
+ return true;
+}
+
+/// layout - linearly layout all output sections and reserve some space
+/// for GOT/PLT
+/// Because we do not support instruction relaxing in this early version,
+/// if there is a branch can not jump to its target, we return false
+/// directly
+bool ObjectLinker::layout()
+{
+ Layout layout;
+ return layout.layout(m_Module, m_LDBackend, m_Config);
+}
+
+/// prelayout - help backend to do some modification after layout
+bool ObjectLinker::postlayout()
+{
+ m_LDBackend.postLayout(m_Module, *m_pLinker);
+ return true;
+}
+
+/// finalizeSymbolValue - finalize the resolved symbol value.
+/// Before relocate(), after layout(), FragmentLinker should correct value of all
+/// symbol.
+bool ObjectLinker::finalizeSymbolValue()
+{
+ return m_pLinker->finalizeSymbols();
+}
+
+/// relocate - applying relocation entries and create relocation
+/// section in the output files
+/// Create relocation section, asking TargetLDBackend to
+/// read the relocation information into RelocationEntry
+/// and push_back into the relocation section
+bool ObjectLinker::relocation()
+{
+ return m_pLinker->applyRelocations();
+}
+
+/// emitOutput - emit the output file.
+bool ObjectLinker::emitOutput(MemoryArea& pOutput)
+{
+ switch(m_Config.codeGenType()) {
+ case LinkerConfig::Object:
+ getObjectWriter()->writeObject(m_Module, pOutput);
+ return true;
+ case LinkerConfig::DynObj:
+ getDynObjWriter()->writeDynObj(m_Module, pOutput);
+ return true;
+ case LinkerConfig::Exec:
+ getExecWriter()->writeExecutable(m_Module, pOutput);
+ return true;
+ default:
+ fatal(diag::unrecognized_output_file) << m_Config.codeGenType();
+ }
+ return false;
+}
+
+/// postProcessing - do modification after all processes
+bool ObjectLinker::postProcessing(MemoryArea& pOutput)
+{
+ m_pLinker->syncRelocationResult(pOutput);
+
+ // emit .eh_frame_hdr
+ // eh_frame_hdr should be emitted after syncRelocation, because eh_frame_hdr
+ // needs FDE PC value, which will be corrected at syncRelocation
+ m_LDBackend.postProcessing(*m_pLinker, pOutput);
+ return true;
+}
+
diff --git a/lib/Object/SectionMap.cpp b/lib/Object/SectionMap.cpp
new file mode 100644
index 0000000..ce987e3
--- /dev/null
+++ b/lib/Object/SectionMap.cpp
@@ -0,0 +1,118 @@
+//===- SectionMap.cpp -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Object/SectionMap.h>
+#include <mcld/ADT/StringHash.h>
+#include <cassert>
+#include <cstring>
+
+using namespace mcld;
+
+
+SectionMap::NamePair SectionMap::NullName;
+
+//===----------------------------------------------------------------------===//
+// SectionMap::NamePair
+//===----------------------------------------------------------------------===//
+SectionMap::NamePair::NamePair()
+ : hash(-1) {
+}
+
+SectionMap::NamePair::NamePair(const std::string& pFrom, const std::string& pTo)
+ : from(pFrom), to(pTo) {
+ hash = SectionMap::hash(pFrom);
+}
+
+bool SectionMap::NamePair::isNull() const
+{
+ return (&NullName == this);
+}
+
+//===----------------------------------------------------------------------===//
+// SectionMap
+//===----------------------------------------------------------------------===//
+const SectionMap::NamePair& SectionMap::find(const std::string& pFrom) const
+{
+ unsigned int hash = SectionMap::hash(pFrom);
+ return find(pFrom, hash);
+}
+
+SectionMap::NamePair& SectionMap::find(const std::string& pFrom)
+{
+ unsigned int hash = SectionMap::hash(pFrom);
+ return find(pFrom, hash);
+}
+
+const SectionMap::NamePair&
+SectionMap::find(const std::string& pFrom, unsigned int pHash) const
+{
+ NamePairList::const_iterator name_hash, nEnd = m_NamePairList.end();
+ for (name_hash = m_NamePairList.begin(); name_hash != nEnd; ++name_hash) {
+ if (matched(*name_hash, pFrom, pHash)) {
+ return *name_hash;
+ }
+ }
+ return NullName;
+}
+
+SectionMap::NamePair&
+SectionMap::find(const std::string& pFrom, unsigned int pHash)
+{
+ NamePairList::iterator name_hash, nEnd = m_NamePairList.end();
+ for (name_hash = m_NamePairList.begin(); name_hash != nEnd; ++name_hash) {
+ if (matched(*name_hash, pFrom, pHash)) {
+ return *name_hash;
+ }
+ }
+ return NullName;
+}
+
+SectionMap::NamePair& SectionMap::append(const std::string &pFrom,
+ const std::string &pTo,
+ bool &pExist)
+{
+ NamePair& result = find(pFrom);
+ if (!result.isNull()) {
+ pExist = true;
+ return result;
+ }
+
+ pExist = false;
+ NamePair entry(pFrom, pTo);
+ m_NamePairList.push_back(entry);
+ return m_NamePairList.back();
+}
+
+bool SectionMap::matched(const NamePair& pNamePair,
+ const std::string& pInput,
+ unsigned int pHashValue) const
+{
+ if ('*' == pNamePair.from[0])
+ return true;
+
+ if (pNamePair.from.size() > pInput.size())
+ return false;
+
+ if (!StringHash<ES>::may_include(pNamePair.hash, pHashValue))
+ return false;
+
+ if (0 == strncmp(pInput.c_str(),
+ pNamePair.from.c_str(),
+ pNamePair.from.size())) {
+ return true;
+ }
+
+ return false;
+}
+
+unsigned int SectionMap::hash(const std::string& pString)
+{
+ static StringHash<ES> hash_func;
+ return hash_func(pString);
+}
+
diff --git a/lib/Support/Android.mk b/lib/Support/Android.mk
index 8e5a7ca..b503a3d 100644
--- a/lib/Support/Android.mk
+++ b/lib/Support/Android.mk
@@ -17,6 +17,8 @@
Space.cpp \
SystemUtils.cpp \
TargetRegistry.cpp \
+ ToolOutputFile.cpp \
+ raw_mem_ostream.cpp \
raw_ostream.cpp
# For the host
diff --git a/lib/Support/FileHandle.cpp b/lib/Support/FileHandle.cpp
index 6d43a4c..4800bfa 100644
--- a/lib/Support/FileHandle.cpp
+++ b/lib/Support/FileHandle.cpp
@@ -9,10 +9,31 @@
#include <mcld/Support/FileHandle.h>
#include <mcld/Support/FileSystem.h>
#include <errno.h>
-#include <fcntl.h>
+
+#if defined(HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+#if defined(HAVE_FCNTL_H)
+# include <fcntl.h>
+#endif
+
#include <sys/stat.h>
#include <sys/mman.h>
+#if defined(_MSC_VER)
+#include <io.h>
+#include <fcntl.h>
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+#endif
+
using namespace mcld;
//===----------------------------------------------------------------------===//
@@ -39,18 +60,18 @@
if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite))
result |= O_RDWR;
- else if (pMode & FileHandle::ReadOnly)
+ else if (FileHandle::ReadOnly == (pMode & FileHandle::ReadOnly))
result |= O_RDONLY;
- else if (pMode & FileHandle::WriteOnly)
+ else if (FileHandle::WriteOnly == (pMode & FileHandle::WriteOnly))
result |= O_WRONLY;
- if (pMode & FileHandle::Append)
+ if (FileHandle::Append == (pMode & FileHandle::Append))
result |= O_APPEND;
- if (pMode & FileHandle::Create)
+ if (FileHandle::Create == (pMode & FileHandle::Create))
result |= O_CREAT;
- if (pMode & FileHandle::Truncate)
+ if (FileHandle::Truncate == (pMode & FileHandle::Truncate))
result |= O_TRUNC;
return result;
@@ -68,31 +89,6 @@
}
bool FileHandle::open(const sys::fs::Path& pPath,
- FileHandle::OpenMode pMode)
-{
- if (isOpened() || Unknown == pMode) {
- setState(BadBit);
- return false;
- }
-
- m_OpenMode = pMode;
- m_Handler = ::open(pPath.native().c_str(), oflag(pMode));
- m_Path = pPath;
- if (-1 == m_Handler) {
- m_OpenMode = NotOpen;
- setState(FailBit);
- return false;
- }
-
- if (!get_size(m_Handler, m_Size)) {
- setState(FailBit);
- return false;
- }
-
- return true;
-}
-
-bool FileHandle::open(const sys::fs::Path& pPath,
FileHandle::OpenMode pMode,
FileHandle::Permission pPerm)
{
@@ -102,7 +98,11 @@
}
m_OpenMode = pMode;
- m_Handler = sys::fs::detail::open(pPath, oflag(pMode), (int)pPerm);
+ if (System == pPerm)
+ m_Handler = sys::fs::detail::open(pPath, oflag(pMode));
+ else
+ m_Handler = sys::fs::detail::open(pPath, oflag(pMode), (int)pPerm);
+
m_Path = pPath;
if (-1 == m_Handler) {
m_OpenMode = NotOpen;
diff --git a/lib/Support/MemoryArea.cpp b/lib/Support/MemoryArea.cpp
index 844d8f6..3a3fa0c 100644
--- a/lib/Support/MemoryArea.cpp
+++ b/lib/Support/MemoryArea.cpp
@@ -6,8 +6,8 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/Support/RegionFactory.h>
#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/Space.h>
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/FileHandle.h>
#include <mcld/Support/MsgHandling.h>
@@ -17,21 +17,26 @@
//===--------------------------------------------------------------------===//
// MemoryArea
//===--------------------------------------------------------------------===//
-
// MemoryArea - special constructor
// This constructor is used for *SPECIAL* situation. I'm sorry I can not
// reveal what is the special situation.
-MemoryArea::MemoryArea(RegionFactory& pRegionFactory, Space& pUniverse)
- : m_RegionFactory(pRegionFactory), m_pFileHandle(NULL) {
- m_SpaceList.push_back(&pUniverse);
+MemoryArea::MemoryArea(Space& pUniverse)
+ : m_pFileHandle(NULL) {
+ m_SpaceMap.insert(std::make_pair(Key(pUniverse.start(), pUniverse.size()),
+ &pUniverse));
}
-MemoryArea::MemoryArea(RegionFactory& pRegionFactory, FileHandle& pFileHandle)
- : m_RegionFactory(pRegionFactory), m_pFileHandle(&pFileHandle) {
+MemoryArea::MemoryArea(FileHandle& pFileHandle)
+ : m_pFileHandle(&pFileHandle) {
}
MemoryArea::~MemoryArea()
{
+ SpaceMapType::iterator space, sEnd = m_SpaceMap.end();
+ for (space = m_SpaceMap.begin(); space != sEnd; ++space) {
+ if (space->second != NULL)
+ Space::Destroy(space->second);
+ }
}
// The layout of MemorySpace in the virtual memory space
@@ -62,8 +67,8 @@
unreachable(diag::err_out_of_range_region) << pOffset << pLength;
}
- space = Space::createSpace(*m_pFileHandle, pOffset, pLength);
- m_SpaceList.push_back(space);
+ space = Space::Create(*m_pFileHandle, pOffset, pLength);
+ m_SpaceMap.insert(std::make_pair(Key(pOffset, pLength), space));
}
// adjust r_start
@@ -71,7 +76,7 @@
void* r_start = space->memory() + distance;
// now, we have a legal space to hold the new MemoryRegion
- return m_RegionFactory.produce(*space, r_start, pLength);
+ return MemoryRegion::Create(r_start, pLength, *space);
}
// release - release a MemoryRegion
@@ -81,7 +86,7 @@
return;
Space *space = pRegion->parent();
- m_RegionFactory.destruct(pRegion);
+ MemoryRegion::Destroy(pRegion);
if (0 == space->numOfRegions()) {
@@ -91,10 +96,10 @@
// Space.
if (m_pFileHandle->isWritable()) {
// synchronize writable space before we release it.
- Space::syncSpace(space, *m_pFileHandle);
+ Space::Sync(space, *m_pFileHandle);
}
- Space::releaseSpace(space, *m_pFileHandle);
- m_SpaceList.erase(space);
+ m_SpaceMap.erase(Key(space->start(), space->size()));
+ Space::Release(space, *m_pFileHandle);
}
}
}
@@ -106,46 +111,44 @@
return;
if (m_pFileHandle->isWritable()) {
- SpaceList::iterator space, sEnd = m_SpaceList.end();
- for (space = m_SpaceList.begin(); space != sEnd; ++space) {
- Space::syncSpace(space, *m_pFileHandle);
- Space::releaseSpace(space, *m_pFileHandle);
+ SpaceMapType::iterator space, sEnd = m_SpaceMap.end();
+ for (space = m_SpaceMap.begin(); space != sEnd; ++space) {
+ Space::Sync(space->second, *m_pFileHandle);
+ Space::Release(space->second, *m_pFileHandle);
}
}
else {
- SpaceList::iterator space, sEnd = m_SpaceList.end();
- for (space = m_SpaceList.begin(); space != sEnd; ++space)
- Space::releaseSpace(space, *m_pFileHandle);
+ SpaceMapType::iterator space, sEnd = m_SpaceMap.end();
+ for (space = m_SpaceMap.begin(); space != sEnd; ++space)
+ Space::Release(space->second, *m_pFileHandle);
}
- m_SpaceList.clear();
+ for (SpaceMapType::iterator space = m_SpaceMap.begin(),
+ sEnd = m_SpaceMap.end(); space != sEnd; ++space) {
+ if (space->second != NULL)
+ Space::Destroy(space->second);
+ }
+ m_SpaceMap.clear();
}
//===--------------------------------------------------------------------===//
// SpaceList methods
+//===--------------------------------------------------------------------===//
Space* MemoryArea::find(size_t pOffset, size_t pLength)
{
- SpaceList::iterator sIter, sEnd = m_SpaceList.end();
- for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
- if (sIter->start() <= pOffset &&
- (pOffset+pLength) <= (sIter->start()+sIter->size()) ) {
- // within
- return sIter;
- }
- }
+ SpaceMapType::iterator it = m_SpaceMap.find(Key(pOffset, pLength));
+ if (it != m_SpaceMap.end())
+ return it->second;
+
return NULL;
}
const Space* MemoryArea::find(size_t pOffset, size_t pLength) const
{
- SpaceList::const_iterator sIter, sEnd = m_SpaceList.end();
- for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
- if (sIter->start() <= pOffset &&
- (pOffset+pLength) <= (sIter->start()+sIter->size()) ) {
- // within
- return sIter;
- }
- }
+ SpaceMapType::const_iterator it = m_SpaceMap.find(Key(pOffset, pLength));
+ if (it != m_SpaceMap.end())
+ return it->second;
+
return NULL;
}
diff --git a/lib/Support/MemoryAreaFactory.cpp b/lib/Support/MemoryAreaFactory.cpp
index 3da07d5..224e0a6 100644
--- a/lib/Support/MemoryAreaFactory.cpp
+++ b/lib/Support/MemoryAreaFactory.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include <mcld/Support/MemoryAreaFactory.h>
#include <mcld/Support/MsgHandling.h>
-#include <mcld/Support/RegionFactory.h>
#include <mcld/Support/SystemUtils.h>
#include <mcld/Support/Space.h>
@@ -16,12 +15,9 @@
//===----------------------------------------------------------------------===//
// MemoryAreaFactory
+//===----------------------------------------------------------------------===//
MemoryAreaFactory::MemoryAreaFactory(size_t pNum)
: GCFactory<MemoryArea, 0>(pNum) {
- // For each loaded file, MCLinker must load ELF header, section header,
- // symbol table, and string table. So, we set the size of chunk quadruple
- // larger than the number of input files.
- m_pRegionFactory = new RegionFactory(pNum*4);
}
MemoryAreaFactory::~MemoryAreaFactory()
@@ -33,8 +29,6 @@
}
delete rec->handle;
}
-
- delete m_pRegionFactory;
}
MemoryArea*
@@ -51,7 +45,7 @@
}
MemoryArea* result = allocate();
- new (result) MemoryArea(*m_pRegionFactory, *handler);
+ new (result) MemoryArea(*handler);
m_HandleToArea.push_back(handler, result);
return result;
@@ -75,7 +69,7 @@
}
MemoryArea* result = allocate();
- new (result) MemoryArea(*m_pRegionFactory, *handler);
+ new (result) MemoryArea(*handler);
m_HandleToArea.push_back(handler, result);
return result;
@@ -84,6 +78,26 @@
return map_result.area;
}
+MemoryArea* MemoryAreaFactory::produce(void* pMemBuffer, size_t pSize)
+{
+ Space* space = Space::Create(pMemBuffer, pSize);
+ MemoryArea* result = allocate();
+ new (result) MemoryArea(*space);
+ return result;
+}
+
+MemoryArea*
+MemoryAreaFactory::produce(int pFD, FileHandle::OpenMode pMode)
+{
+ FileHandle* handler = new FileHandle();
+ handler->delegate(pFD, pMode);
+
+ MemoryArea* result = allocate();
+ new (result) MemoryArea(*handler);
+
+ return result;
+}
+
void MemoryAreaFactory::destruct(MemoryArea* pArea)
{
m_HandleToArea.erase(pArea);
@@ -93,24 +107,3 @@
deallocate(pArea);
}
-MemoryArea*
-MemoryAreaFactory::create(void* pMemBuffer, size_t pSize)
-{
- Space* space = new Space(Space::EXTERNAL, pMemBuffer, pSize);
- MemoryArea* result = allocate();
- new (result) MemoryArea(*m_pRegionFactory, *space);
- return result;
-}
-
-MemoryArea*
-MemoryAreaFactory::create(int pFD, FileHandle::OpenMode pMode)
-{
- FileHandle* handler = new FileHandle();
- handler->delegate(pFD, pMode);
-
- MemoryArea* result = allocate();
- new (result) MemoryArea(*m_pRegionFactory, *handler);
-
- return result;
-}
-
diff --git a/lib/Support/MemoryRegion.cpp b/lib/Support/MemoryRegion.cpp
index 32e790b..410500a 100644
--- a/lib/Support/MemoryRegion.cpp
+++ b/lib/Support/MemoryRegion.cpp
@@ -7,18 +7,51 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/RegionFactory.h>
+
+#include <llvm/Support/ManagedStatic.h>
using namespace mcld;
-//==========================
+static llvm::ManagedStatic<RegionFactory> g_RegionFactory;
+
+//===----------------------------------------------------------------------===//
// MemoryRegion
-MemoryRegion::MemoryRegion(Space& pParent,
- MemoryRegion::Address pVMAStart,
- size_t pSize)
- : m_Parent(pParent), m_VMAStart(pVMAStart), m_Length(pSize) {
+//===----------------------------------------------------------------------===//
+MemoryRegion::MemoryRegion()
+ : m_pParent(NULL), m_VMAStart(0), m_Length(0) {
+}
+
+MemoryRegion::MemoryRegion(MemoryRegion::Address pVMAStart, size_t pSize)
+ : m_pParent(NULL), m_VMAStart(pVMAStart), m_Length(pSize) {
}
MemoryRegion::~MemoryRegion()
{
}
+MemoryRegion* MemoryRegion::Create(void* pStart, size_t pSize)
+{
+ return g_RegionFactory->produce(static_cast<Address>(pStart), pSize);
+}
+
+MemoryRegion* MemoryRegion::Create(void* pStart, size_t pSize, Space& pSpace)
+{
+ MemoryRegion* result = g_RegionFactory->produce(static_cast<Address>(pStart),
+ pSize);
+ result->setParent(pSpace);
+ pSpace.addRegion(*result);
+ return result;
+}
+
+void MemoryRegion::Destroy(MemoryRegion*& pRegion)
+{
+ if (NULL == pRegion)
+ return;
+
+ if (pRegion->hasParent())
+ pRegion->parent()->removeRegion(*pRegion);
+ g_RegionFactory->destruct(pRegion);
+ pRegion = NULL;
+}
+
diff --git a/lib/Support/MsgHandling.cpp b/lib/Support/MsgHandling.cpp
index d7611d2..fdcf13f 100644
--- a/lib/Support/MsgHandling.cpp
+++ b/lib/Support/MsgHandling.cpp
@@ -9,10 +9,16 @@
#include <mcld/LD/DiagnosticEngine.h>
#include <mcld/LD/DiagnosticLineInfo.h>
#include <mcld/LD/DiagnosticPrinter.h>
+#include <mcld/LD/TextDiagnosticPrinter.h>
#include <mcld/LD/MsgHandler.h>
#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/raw_ostream.h>
+
#include <llvm/Support/ManagedStatic.h>
#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/Signals.h>
+
+#include <cstdlib>
using namespace mcld;
@@ -22,18 +28,14 @@
static llvm::ManagedStatic<DiagnosticEngine> g_pEngine;
void
-mcld::InitializeDiagnosticEngine(const mcld::MCLDInfo& pLDInfo,
- DiagnosticLineInfo* pLineInfo,
+mcld::InitializeDiagnosticEngine(const mcld::LinkerConfig& pConfig,
DiagnosticPrinter* pPrinter)
{
- g_pEngine->reset(pLDInfo);
- if (NULL != pLineInfo)
- g_pEngine->setLineInfo(*pLineInfo);
-
+ g_pEngine->reset(pConfig);
if (NULL != pPrinter)
g_pEngine->setPrinter(*pPrinter, false);
else {
- DiagnosticPrinter* printer = new DiagnosticPrinter();
+ DiagnosticPrinter* printer = new TextDiagnosticPrinter(mcld::errs(), pConfig);
g_pEngine->setPrinter(*printer, true);
}
}
@@ -43,3 +45,21 @@
return *g_pEngine;
}
+bool mcld::Diagnose()
+{
+ if (g_pEngine->getPrinter()->getNumErrors() > 0) {
+ // If we reached here, we are failing ungracefully. Run the interrupt handlers
+ // to make sure any special cleanups get done, in particular that we remove
+ // files registered with RemoveFileOnSignal.
+ llvm::sys::RunInterruptHandlers();
+ g_pEngine->getPrinter()->finish();
+ return false;
+ }
+ return true;
+}
+
+void mcld::FinalizeDiagnosticEngine()
+{
+ g_pEngine->getPrinter()->finish();
+}
+
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp
index 7f516f6..d359162 100644
--- a/lib/Support/Path.cpp
+++ b/lib/Support/Path.cpp
@@ -148,6 +148,16 @@
return Path();
}
+Path Path::filename() const
+{
+ size_t pos = m_PathName.find_last_of(separator);
+ if (pos != StringType::npos) {
+ ++pos;
+ return Path(m_PathName.substr(pos));
+ }
+ return Path(*this);
+}
+
Path Path::stem() const
{
size_t begin_pos = m_PathName.find_last_of(separator)+1;
diff --git a/lib/Support/RegionFactory.cpp b/lib/Support/RegionFactory.cpp
index ddce433..7ed87f1 100644
--- a/lib/Support/RegionFactory.cpp
+++ b/lib/Support/RegionFactory.cpp
@@ -7,34 +7,23 @@
//
//===----------------------------------------------------------------------===//
#include <mcld/Support/RegionFactory.h>
-#include <mcld/Support/MemoryArea.h>
#include <mcld/Support/Space.h>
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// RegionFactory
-RegionFactory::RegionFactory(size_t pNum)
- : GCFactory<MemoryRegion, 0>(pNum) {
-}
-
-RegionFactory::~RegionFactory()
-{
-}
-
-MemoryRegion* RegionFactory::produce(Space& pSpace, void* pVMAStart, size_t pSize)
+//===----------------------------------------------------------------------===//
+MemoryRegion*
+RegionFactory::produce(Address pVMAStart, size_t pSize)
{
MemoryRegion* result = Alloc::allocate();
- new (result) MemoryRegion(pSpace,
- static_cast<const MemoryRegion::Address>(pVMAStart),
- pSize);
- pSpace.addRegion(*result);
+ new (result) MemoryRegion(pVMAStart, pSize);
return result;
}
void RegionFactory::destruct(MemoryRegion* pRegion)
{
- pRegion->parent()->removeRegion(*pRegion);
destroy(pRegion);
deallocate(pRegion);
}
diff --git a/lib/Support/Space.cpp b/lib/Support/Space.cpp
index 4024da1..6ec2c53 100644
--- a/lib/Support/Space.cpp
+++ b/lib/Support/Space.cpp
@@ -20,11 +20,12 @@
//===----------------------------------------------------------------------===//
// Non-member functions
+//===----------------------------------------------------------------------===//
//
// low address A page high address
// |--------------------|------------------|
// ^ page_offset ^ pFileOffset ^ page_boundary
-
+//
// Given a file offset, return the page offset.
// return the first page boundary \b before pFileOffset
inline static off_t page_offset(off_t pFileOffset)
@@ -46,6 +47,7 @@
//===----------------------------------------------------------------------===//
// Space
+//===----------------------------------------------------------------------===//
Space::Space()
: m_Data(NULL), m_StartOffset(0), m_Size(0),
m_RegionCount(0), m_Type(UNALLOCATED) {
@@ -62,13 +64,18 @@
// do nothing. m_Data is deleted by @ref releaseSpace
}
-Space* Space::createSpace(FileHandle& pHandler,
- size_t pStart, size_t pSize)
+Space* Space::Create(void* pMemBuffer, size_t pSize)
+{
+ Space* result = new Space(EXTERNAL, pMemBuffer, pSize);
+ return result;
+}
+
+Space* Space::Create(FileHandle& pHandler, size_t pStart, size_t pSize)
{
Type type;
- void* memory;
+ void* memory = NULL;
Space* result = NULL;
- size_t start, size = 0, total_offset;
+ size_t start = 0, size = 0, total_offset;
switch(type = policy(pStart, pSize)) {
case ALLOCATED_ARRAY: {
// adjust total_offset, start and size
@@ -134,7 +141,13 @@
return result;
}
-void Space::releaseSpace(Space* pSpace, FileHandle& pHandler)
+void Space::Destroy(Space*& pSpace)
+{
+ delete pSpace;
+ pSpace = NULL;
+}
+
+void Space::Release(Space* pSpace, FileHandle& pHandler)
{
if (NULL == pSpace)
return;
@@ -152,7 +165,7 @@
} // end of switch
}
-void Space::syncSpace(Space* pSpace, FileHandle& pHandler)
+void Space::Sync(Space* pSpace, FileHandle& pHandler)
{
if (NULL == pSpace || !pHandler.isWritable())
return;
diff --git a/lib/Support/ToolOutputFile.cpp b/lib/Support/ToolOutputFile.cpp
new file mode 100644
index 0000000..80bae12
--- /dev/null
+++ b/lib/Support/ToolOutputFile.cpp
@@ -0,0 +1,108 @@
+//===- ToolOutputFile.cpp -------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/ToolOutputFile.h>
+
+#include <mcld/Support/Path.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/raw_mem_ostream.h>
+
+#include <mcld/Support/SystemUtils.h>
+#include <mcld/Support/MsgHandling.h>
+
+#include <llvm/Support/Signals.h>
+#include <llvm/Support/Path.h>
+#include <llvm/Support/FormattedStream.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// CleanupInstaller
+//===----------------------------------------------------------------------===//
+ToolOutputFile::CleanupInstaller::CleanupInstaller(const std::string& pName)
+ : Keep(false), m_Filename(pName) {
+ // Arrange for the file to be deleted if the process is killed.
+ if (m_Filename != "-")
+ llvm::sys::RemoveFileOnSignal(llvm::sys::Path(m_Filename));
+}
+
+ToolOutputFile::CleanupInstaller::~CleanupInstaller()
+{
+ // Delete the file if the client hasn't told us not to.
+ if (!Keep && m_Filename != "-")
+ llvm::sys::Path(m_Filename).eraseFromDisk();
+
+ // Ok, the file is successfully written and closed, or deleted. There's no
+ // further need to clean it up on signals.
+ if (m_Filename != "-")
+ llvm::sys::DontRemoveFileOnSignal(llvm::sys::Path(m_Filename));
+}
+
+//===----------------------------------------------------------------------===//
+// ToolOutputFile
+//===----------------------------------------------------------------------===//
+ToolOutputFile::ToolOutputFile(const sys::fs::Path& pPath,
+ FileHandle::OpenMode pMode,
+ FileHandle::Permission pPermission)
+ : m_Installer(pPath.native()),
+ m_pMemoryArea(NULL),
+ m_pOStream(NULL),
+ m_pFOStream(NULL) {
+
+ if (!m_FileHandle.open(pPath, pMode, pPermission)) {
+ // If open fails, no clean-up is needed.
+ m_Installer.Keep = true;
+ fatal(diag::err_cannot_open_output_file)
+ << pPath
+ << sys::strerror(m_FileHandle.error());
+ return;
+ }
+
+ m_pMemoryArea = new MemoryArea(m_FileHandle);
+ m_pOStream = new raw_mem_ostream(*m_pMemoryArea);
+}
+
+ToolOutputFile::~ToolOutputFile()
+{
+ delete m_pFOStream;
+ delete m_pOStream;
+ delete m_pMemoryArea;
+}
+
+void ToolOutputFile::keep()
+{
+ m_Installer.Keep = true;
+}
+
+/// mem_os - Return the contained raw_mem_ostream.
+raw_mem_ostream& ToolOutputFile::mem_os()
+{
+ assert(NULL != m_pOStream);
+ return *m_pOStream;
+}
+
+/// formatted_os - Return the containeed formatted_raw_ostream.
+/// Since formatted_os is rarely used, we lazily initialize it.
+llvm::formatted_raw_ostream& ToolOutputFile::formatted_os()
+{
+ if (NULL == m_pFOStream) {
+ assert(NULL != m_pOStream);
+ m_pFOStream = new llvm::formatted_raw_ostream(*m_pOStream);
+ }
+
+ return *m_pFOStream;
+}
+
+/// memory - Return the contained MemoryArea.
+MemoryArea& ToolOutputFile::memory()
+{
+ assert(NULL != m_pOStream);
+ return m_pOStream->getMemoryArea();
+}
+
diff --git a/lib/Support/raw_mem_ostream.cpp b/lib/Support/raw_mem_ostream.cpp
new file mode 100644
index 0000000..c3066dd
--- /dev/null
+++ b/lib/Support/raw_mem_ostream.cpp
@@ -0,0 +1,46 @@
+//===- raw_mem_ostream.cpp ------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/raw_mem_ostream.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/FileHandle.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// raw_mem_ostream
+//===----------------------------------------------------------------------===//
+raw_mem_ostream::raw_mem_ostream(MemoryArea &pMemoryArea)
+ : m_MemoryArea(pMemoryArea), m_Position(0) {
+ if (NULL == m_MemoryArea.handler() ||
+ !(m_MemoryArea.handler()->isGood() &&
+ m_MemoryArea.handler()->isWritable())) {
+ fatal(diag::fatal_unwritable_output) << m_MemoryArea.handler()->path();
+ }
+}
+
+raw_mem_ostream::~raw_mem_ostream()
+{
+ flush();
+ m_MemoryArea.clear();
+}
+
+void raw_mem_ostream::write_impl(const char *pPtr, size_t pSize)
+{
+ MemoryRegion* region = m_MemoryArea.request(m_Position, pSize);
+ memcpy(region->start(), pPtr, pSize);
+ m_Position += pSize;
+}
+
+uint64_t raw_mem_ostream::current_pos() const
+{
+ return m_Position;
+}
+
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
index 2453c2c..e294bc3 100644
--- a/lib/Support/raw_ostream.cpp
+++ b/lib/Support/raw_ostream.cpp
@@ -8,31 +8,52 @@
//===----------------------------------------------------------------------===//
#include <mcld/Support/raw_ostream.h>
+#if defined(HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#if defined(_MSC_VER)
+#include <io.h>
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+#endif
+
using namespace mcld;
//===----------------------------------------------------------------------===//
// raw_ostream
+//===----------------------------------------------------------------------===//
mcld::raw_fd_ostream::raw_fd_ostream(const char *pFilename,
- std::string &pErrorInfo,
- unsigned int pFlags,
- const MCLDInfo* pLDInfo)
- : llvm::raw_fd_ostream(pFilename, pErrorInfo, pFlags), m_pLDInfo(pLDInfo) {
+ std::string &pErrorInfo,
+ unsigned int pFlags)
+ : llvm::raw_fd_ostream(pFilename, pErrorInfo, pFlags),
+ m_bConfigColor(false),
+ m_bSetColor(false) {
}
mcld::raw_fd_ostream::raw_fd_ostream(int pFD,
bool pShouldClose,
- bool pUnbuffered,
- const MCLDInfo* pLDInfo)
- : llvm::raw_fd_ostream(pFD, pShouldClose, pUnbuffered), m_pLDInfo(pLDInfo) {
+ bool pUnbuffered)
+ : llvm::raw_fd_ostream(pFD, pShouldClose, pUnbuffered),
+ m_bConfigColor(false),
+ m_bSetColor(false) {
}
mcld::raw_fd_ostream::~raw_fd_ostream()
{
}
-void mcld::raw_fd_ostream::setLDInfo(const MCLDInfo& pLDInfo)
+void mcld::raw_fd_ostream::setColor(bool pEnable)
{
- m_pLDInfo = &pLDInfo;
+ m_bConfigColor = true;
+ m_bSetColor = pEnable;
}
llvm::raw_ostream &
@@ -52,22 +73,19 @@
return llvm::raw_fd_ostream::resetColor();
}
-// FIXME: migrate to newer LLVM
-/**
llvm::raw_ostream& mcld::raw_fd_ostream::reverseColor()
{
if (!is_displayed())
return *this;
return llvm::raw_ostream::reverseColor();
}
-**/
bool mcld::raw_fd_ostream::is_displayed() const
{
- if (NULL == m_pLDInfo)
- return llvm::raw_fd_ostream::is_displayed();
+ if (m_bConfigColor)
+ return m_bSetColor;
- return m_pLDInfo->options().color();
+ return llvm::raw_fd_ostream::is_displayed();
}
//===----------------------------------------------------------------------===//
@@ -77,19 +95,13 @@
// Set buffer settings to model stdout behavior.
// Delete the file descriptor when the program exists, forcing error
// detection. If you don't want this behavior, don't use outs().
- static mcld::raw_fd_ostream S(STDOUT_FILENO, true, NULL);
+ static mcld::raw_fd_ostream S(STDOUT_FILENO, true);
return S;
}
mcld::raw_fd_ostream& mcld::errs() {
// Set standard error to be unbuffered by default.
- static mcld::raw_fd_ostream S(STDERR_FILENO, false, true, NULL);
+ static mcld::raw_fd_ostream S(STDERR_FILENO, false, true);
return S;
}
-void mcld::InitializeOStreams(const MCLDInfo& pLDInfo)
-{
- outs().setLDInfo(pLDInfo);
- errs().setLDInfo(pLDInfo);
-}
-
diff --git a/lib/Target/ARM/ARMDiagnostic.cpp b/lib/Target/ARM/ARMDiagnostic.cpp
index d6f3988..b63a192 100644
--- a/lib/Target/ARM/ARMDiagnostic.cpp
+++ b/lib/Target/ARM/ARMDiagnostic.cpp
@@ -31,7 +31,7 @@
//==========================
// InitializeARMDiagnostic
-extern "C" void LLVMInitializeARMDiagnosticLineInfo() {
+extern "C" void MCLDInitializeARMDiagnosticLineInfo() {
// Register the linker frontend
mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheARMTarget, createARMDiagLineInfo);
mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheThumbTarget, createARMDiagLineInfo);
diff --git a/lib/Target/ARM/ARMELFMCLinker.cpp b/lib/Target/ARM/ARMELFMCLinker.cpp
new file mode 100644
index 0000000..daccc84
--- /dev/null
+++ b/lib/Target/ARM/ARMELFMCLinker.cpp
@@ -0,0 +1,25 @@
+//===- ARMELFMCLinker.cpp -------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ARMELFMCLinker.h"
+
+#include <mcld/LinkerConfig.h>
+#include <mcld/Object/SectionMap.h>
+
+using namespace mcld;
+
+ARMELFMCLinker::ARMELFMCLinker(LinkerConfig& pConfig,
+ mcld::Module &pModule,
+ MemoryArea& pOutput)
+ : ELFMCLinker(pConfig, pModule, pOutput) {
+}
+
+ARMELFMCLinker::~ARMELFMCLinker()
+{
+}
+
diff --git a/lib/Target/ARM/ARMELFMCLinker.h b/lib/Target/ARM/ARMELFMCLinker.h
new file mode 100644
index 0000000..91f297f
--- /dev/null
+++ b/lib/Target/ARM/ARMELFMCLinker.h
@@ -0,0 +1,37 @@
+//===- ARMELFMCLinker.h ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef ARM_ELF_SECTION_LINKER_H
+#define ARM_ELF_SECTION_LINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Target/ELFMCLinker.h>
+
+namespace mcld {
+
+class Module;
+class MemoryArea;
+
+/** \class ARMELFMCLinker
+ * \brief ARMELFMCLinker sets up the environment for linking.
+ */
+class ARMELFMCLinker : public ELFMCLinker
+{
+public:
+ ARMELFMCLinker(LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ MemoryArea& pOutput);
+
+ ~ARMELFMCLinker();
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/ARM/ARMELFSectLinker.cpp b/lib/Target/ARM/ARMELFSectLinker.cpp
deleted file mode 100644
index 0395606..0000000
--- a/lib/Target/ARM/ARMELFSectLinker.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- ARMELFSectLinker.cpp -----------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "ARMELFSectLinker.h"
-
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-ARMELFSectLinker::ARMELFSectLinker(SectLinkerOption &pOption,
- TargetLDBackend &pLDBackend)
- : SectLinker(pOption,
- pLDBackend) {
- MCLDInfo &info = pOption.info();
- // set up target-dependent constraints of attributes
- info.attrFactory().constraint().enableWholeArchive();
- info.attrFactory().constraint().disableAsNeeded();
- info.attrFactory().constraint().setSharedSystem();
-
- // set up the predefined attributes
- info.attrFactory().predefined().setWholeArchive();
- info.attrFactory().predefined().setDynamic();
-
-}
-
-ARMELFSectLinker::~ARMELFSectLinker()
-{
-}
-
diff --git a/lib/Target/ARM/ARMELFSectLinker.h b/lib/Target/ARM/ARMELFSectLinker.h
deleted file mode 100644
index ab626b9..0000000
--- a/lib/Target/ARM/ARMELFSectLinker.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- ARMELFSectLinker.h -------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef ARM_ELF_SECTION_LINKER_H
-#define ARM_ELF_SECTION_LINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/CodeGen/SectLinker.h>
-
-namespace mcld
-{
-
-/** \class ARMELFSectLinker
- * \brief ARMELFSectLinker sets up the environment for linking.
- *
- * \see
- */
-class ARMELFSectLinker : public SectLinker
-{
-public:
- ARMELFSectLinker(SectLinkerOption &pOption,
- mcld::TargetLDBackend &pLDBackend);
-
- ~ARMELFSectLinker();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/lib/Target/ARM/ARMEmulation.cpp b/lib/Target/ARM/ARMEmulation.cpp
new file mode 100644
index 0000000..875d229
--- /dev/null
+++ b/lib/Target/ARM/ARMEmulation.cpp
@@ -0,0 +1,69 @@
+//===- ARMEmulation.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ARM.h"
+#include <mcld/LinkerConfig.h>
+#include <mcld/Target/ELFEmulation.h>
+#include <mcld/Support/TargetRegistry.h>
+
+namespace mcld {
+
+static bool MCLDEmulateARMELF(LinkerConfig& pConfig)
+{
+ if (!MCLDEmulateELF(pConfig))
+ return false;
+
+ // set up target-dependent constraints of attributes
+ pConfig.attribute().constraint().enableWholeArchive();
+ pConfig.attribute().constraint().enableAsNeeded();
+ pConfig.attribute().constraint().setSharedSystem();
+
+ // set up the predefined attributes
+ pConfig.attribute().predefined().unsetWholeArchive();
+ pConfig.attribute().predefined().unsetAsNeeded();
+ pConfig.attribute().predefined().setDynamic();
+
+ // set up section map
+ if (pConfig.codeGenType() != LinkerConfig::Object) {
+ bool exist = false;
+ pConfig.scripts().sectionMap().append(".ARM.exidx", ".ARM.exidx", exist);
+ pConfig.scripts().sectionMap().append(".ARM.extab", ".ARM.extab", exist);
+ pConfig.scripts().sectionMap().append(".ARM.attributes", ".ARM.attributes", exist);
+ }
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// emulateARMLD - the help function to emulate ARM ld
+//===----------------------------------------------------------------------===//
+bool emulateARMLD(const std::string& pTriple, LinkerConfig& pConfig)
+{
+ llvm::Triple theTriple(pTriple);
+ if (theTriple.isOSDarwin()) {
+ assert(0 && "MachO linker has not supported yet");
+ return false;
+ }
+ if (theTriple.isOSWindows()) {
+ assert(0 && "COFF linker has not supported yet");
+ return false;
+ }
+
+ return MCLDEmulateARMELF(pConfig);
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// ARMEmulation
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeARMEmulation() {
+ // Register the emulation
+ mcld::TargetRegistry::RegisterEmulation(mcld::TheARMTarget, mcld::emulateARMLD);
+ mcld::TargetRegistry::RegisterEmulation(mcld::TheThumbTarget, mcld::emulateARMLD);
+}
+
diff --git a/lib/Target/ARM/ARMGOT.cpp b/lib/Target/ARM/ARMGOT.cpp
index 200bcb5..3d2d07a 100644
--- a/lib/Target/ARM/ARMGOT.cpp
+++ b/lib/Target/ARM/ARMGOT.cpp
@@ -12,172 +12,134 @@
#include <llvm/Support/Casting.h>
+#include <mcld/LD/LDSection.h>
#include <mcld/LD/LDFileFormat.h>
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/MsgHandling.h>
namespace {
const size_t ARMGOTEntrySize = 4;
+ const unsigned int ARMGOT0Num = 3;
} // end of anonymous namespace
using namespace mcld;
//===----------------------------------------------------------------------===//
// ARMGOT
-ARMGOT::ARMGOT(LDSection& pSection, SectionData& pSectionData)
- : GOT(pSection, pSectionData, ARMGOTEntrySize),
- m_NormalGOTIterator(), m_GOTPLTIterator(),
- m_GOTPLTBegin(), m_GOTPLTEnd()
+ARMGOT::ARMGOT(LDSection& pSection)
+ : GOT(pSection, ARMGOTEntrySize)
{
- GOTEntry* Entry = 0;
-
// Create GOT0 entries.
- for (int i = 0; i < 3; i++) {
- Entry = new (std::nothrow) GOTEntry(0, ARMGOTEntrySize,
- &m_SectionData);
-
- if (!Entry)
- fatal(diag::fail_allocate_memory_got);
-
- m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
- }
+ reserve(ARMGOT0Num);
// Skip GOT0 entries.
- iterator it = m_SectionData.begin();
-
- for (int i = 1; i < ARMGOT0Num; ++i) {
- assert((it != m_SectionData.end()) && "Generation of GOT0 entries is incomplete!");
- ++it;
+ for (unsigned int i = 0; i < ARMGOT0Num; ++i) {
+ consume();
}
-
- m_NormalGOTIterator = it;
- m_GOTPLTIterator = it;
-
- m_GOTPLTBegin = it;
- m_GOTPLTEnd = it;
}
ARMGOT::~ARMGOT()
{
}
-void ARMGOT::reserveEntry(size_t pNum)
+bool ARMGOT::hasGOT1() const
{
- GOTEntry* Entry = 0;
+ return (m_SectionData->size() > ARMGOT0Num);
+}
- for (size_t i = 0; i < pNum; i++) {
- Entry = new (std::nothrow) GOTEntry(0, ARMGOTEntrySize,
- &m_SectionData);
-
- if (!Entry)
- fatal(diag::fail_allocate_memory_got);
-
- m_Section.setSize(m_Section.size() + ARMGOTEntrySize);
+void ARMGOT::reserveGOTPLT()
+{
+ Entry* entry = new Entry(0, getEntrySize(), m_SectionData);
+ if (NULL == m_GOTPLT.front) {
+ // GOTPLT is empty
+ if (NULL == m_GOT.front) {
+ // GOT part is also empty. Since entry is the last entry, we can assign
+ // it to GOTPLT directly.
+ m_GOTPLT.front = entry;
+ }
+ else {
+ // GOTn is not empty. Shift GOTn backward by one entry.
+ m_GOTPLT.front = m_GOT.front;
+ m_GOT.front = llvm::cast<GOT::Entry>(m_GOT.front->getNextNode());
+ }
+ }
+ else {
+ // GOTPLT is not empty
+ if (NULL != m_GOT.front)
+ m_GOT.front = llvm::cast<GOT::Entry>(m_GOT.front->getNextNode());
}
}
-void ARMGOT::reserveGOTPLTEntry()
+void ARMGOT::reserveGOT()
{
- GOTEntry* got_entry = 0;
-
- got_entry= new GOTEntry(0, getEntrySize(),&(getSectionData()));
-
- if (!got_entry)
- fatal(diag::fail_allocate_memory_got);
-
- m_Section.setSize(m_Section.size() + getEntrySize());
-
- ++m_GOTPLTEnd;
- ++m_NormalGOTIterator;
+ Entry* entry = new Entry(0, getEntrySize(), m_SectionData);
+ if (NULL == m_GOT.front) {
+ // Entry must be the last entry. We can directly assign it to GOT part.
+ m_GOT.front = entry;
+ }
}
-GOTEntry* ARMGOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
+GOT::Entry* ARMGOT::consumeGOTPLT()
{
- GOTEntry *&Entry = m_NormalGOTMap[&pInfo];
- pExist = 1;
+ assert(NULL != m_GOTPLT.front && "Consuming empty GOTPLT section!");
- if (!Entry) {
- pExist = 0;
-
- ++m_NormalGOTIterator;
- assert(m_NormalGOTIterator != m_SectionData.getFragmentList().end()
- && "The number of GOT Entries and ResolveInfo doesn't match!");
-
- Entry = llvm::cast<GOTEntry>(&(*m_NormalGOTIterator));
+ if (NULL == m_GOTPLT.last_used) {
+ m_GOTPLT.last_used = m_GOTPLT.front;
}
+ else {
+ m_GOTPLT.last_used = llvm::cast<GOT::Entry>(m_GOTPLT.last_used->getNextNode());
+ assert(m_GOTPLT.last_used != m_GOT.front && "No GOT/PLT entry to consume!");
+ }
+ return m_GOTPLT.last_used;
+}
- return Entry;
+GOT::Entry* ARMGOT::consumeGOT()
+{
+ assert(NULL != m_GOT.front && "Consuming empty GOT section!");
+
+ if (NULL == m_GOT.last_used) {
+ m_GOT.last_used = m_GOT.front;
+ }
+ else {
+ m_GOT.last_used = llvm::cast<GOT::Entry>(m_GOT.last_used->getNextNode());
+ assert(m_GOT.last_used != NULL && "No GOTn entry to consume!");
+ }
+ return m_GOT.last_used;
}
void ARMGOT::applyGOT0(uint64_t pAddress)
{
- llvm::cast<GOTEntry>
- (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
+ llvm::cast<Entry>
+ (*(m_SectionData->getFragmentList().begin())).setContent(pAddress);
}
-void ARMGOT::applyAllGOTPLT(uint64_t pPLTBase)
+void ARMGOT::applyGOTPLT(uint64_t pPLTBase)
{
- iterator begin = getGOTPLTBegin();
- iterator end = getGOTPLTEnd();
+ if (NULL == m_GOTPLT.front)
+ return;
- for (;begin != end ;++begin)
- llvm::cast<GOTEntry>(*begin).setContent(pPLTBase);
-}
+ SectionData::iterator entry(m_GOTPLT.front);
+ SectionData::iterator e_end;
+ if (NULL == m_GOT.front)
+ e_end = m_SectionData->end();
+ else
+ e_end = SectionData::iterator(m_GOT.front);
-GOTEntry*& ARMGOT::lookupGOTPLTMap(const ResolveInfo& pSymbol)
-{
- return m_GOTPLTMap[&pSymbol];
-}
-
-ARMGOT::iterator ARMGOT::begin()
-{
- return m_SectionData.getFragmentList().begin();
-}
-
-ARMGOT::const_iterator ARMGOT::begin() const
-{
- return m_SectionData.getFragmentList().begin();
-}
-
-ARMGOT::iterator ARMGOT::end()
-{
- return m_SectionData.getFragmentList().end();
-}
-
-ARMGOT::const_iterator ARMGOT::end() const
-{
- return m_SectionData.getFragmentList().end();
-}
-
-ARMGOT::iterator ARMGOT::getNextGOTPLTEntry()
-{
- return ++m_GOTPLTIterator;
-}
-
-ARMGOT::iterator ARMGOT::getGOTPLTBegin()
-{
- // Move to the first GOTPLT entry from last GOT0 entry.
- iterator begin = m_GOTPLTBegin;
- return ++begin;
-}
-
-const ARMGOT::iterator ARMGOT::getGOTPLTEnd()
-{
- // Move to end or the first normal GOT entry from the last GOTPLT entry.
- iterator end = m_GOTPLTEnd;
- return ++end;
+ while (entry != e_end) {
+ llvm::cast<GOT::Entry>(entry)->setContent(pPLTBase);
+ ++entry;
+ }
}
uint64_t ARMGOT::emit(MemoryRegion& pRegion)
{
uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
- GOTEntry* got = 0;
+ Entry* got = 0;
unsigned int entry_size = getEntrySize();
uint64_t result = 0x0;
- for (iterator it = begin(), ie = end();
- it != ie; ++it, ++buffer) {
- got = &(llvm::cast<GOTEntry>((*it)));
+ for (iterator it = begin(), ie = end(); it != ie; ++it, ++buffer) {
+ got = &(llvm::cast<Entry>((*it)));
*buffer = static_cast<uint32_t>(got->getContent());
result += entry_size;
}
diff --git a/lib/Target/ARM/ARMGOT.h b/lib/Target/ARM/ARMGOT.h
index 13d3424..1e8f383 100644
--- a/lib/Target/ARM/ARMGOT.h
+++ b/lib/Target/ARM/ARMGOT.h
@@ -15,78 +15,66 @@
#include <llvm/ADT/DenseMap.h>
#include <mcld/Target/GOT.h>
-#include <mcld/LD/SectionData.h>
-namespace mcld
-{
+namespace mcld {
+
class LDSection;
class MemoryRegion;
/** \class ARMGOT
* \brief ARM Global Offset Table.
+ *
+ * ARM GOT integrates traditional .got.plt and .got sections into one.
+ * Traditional .got.plt is placed in the front part of GOT (PLTGOT), and
+ * traditional .got is placed in the rear part of GOT (GOT).
+ *
+ * ARM .got
+ * +--------------+
+ * | GOT0 |
+ * +--------------+
+ * | GOTPLT |
+ * +--------------+
+ * | GOT |
+ * +--------------+
+ *
*/
class ARMGOT : public GOT
{
- typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
-
public:
- typedef SectionData::iterator iterator;
- typedef SectionData::const_iterator const_iterator;
-
- enum {
- ARMGOT0Num = 3
- };
-
-public:
- ARMGOT(LDSection &pSection, SectionData& pSectionData);
+ ARMGOT(LDSection &pSection);
~ARMGOT();
- iterator begin();
+ void reserveGOTPLT();
- const_iterator begin() const;
+ void reserveGOT();
- iterator end();
+ GOT::Entry* consumeGOT();
- const_iterator end() const;
+ GOT::Entry* consumeGOTPLT();
uint64_t emit(MemoryRegion& pRegion);
-// For GOT0
-public:
+
void applyGOT0(uint64_t pAddress);
-// For normal GOT
-public:
- // Reserve normal GOT entries.
- void reserveEntry(size_t pNum = 1);
+ void applyGOTPLT(uint64_t pPLTBase);
- GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist);
-
-// For GOTPLT
-public:
- void reserveGOTPLTEntry();
-
- void applyAllGOTPLT(uint64_t pPLTBase);
-
- GOTEntry*& lookupGOTPLTMap(const ResolveInfo& pSymbol);
-
- iterator getNextGOTPLTEntry();
-
- iterator getGOTPLTBegin();
-
- const iterator getGOTPLTEnd();
+ bool hasGOT1() const;
private:
- // For normal GOT entries
- iterator m_NormalGOTIterator;
- SymbolIndexMapType m_NormalGOTMap;
+ struct Part {
+ public:
+ Part() : front(NULL), last_used(NULL) { }
- // For GOTPLT entries
- iterator m_GOTPLTIterator;
- SymbolIndexMapType m_GOTPLTMap;
+ public:
+ GOT::Entry* front;
+ GOT::Entry* last_used;
+ };
- iterator m_GOTPLTBegin;
- iterator m_GOTPLTEnd;
+private:
+ Part m_GOTPLT;
+ Part m_GOT;
+
};
} // namespace of mcld
diff --git a/lib/Target/ARM/ARMLDBackend.cpp b/lib/Target/ARM/ARMLDBackend.cpp
index a44f1da..a90ae63 100644
--- a/lib/Target/ARM/ARMLDBackend.cpp
+++ b/lib/Target/ARM/ARMLDBackend.cpp
@@ -10,6 +10,10 @@
#include "ARMELFDynamic.h"
#include "ARMLDBackend.h"
#include "ARMRelocationFactory.h"
+#include "ARMToARMStub.h"
+#include "ARMToTHMStub.h"
+#include "THMToTHMStub.h"
+#include "THMToARMStub.h"
#include <cstring>
@@ -18,30 +22,39 @@
#include <llvm/Support/ELF.h>
#include <llvm/Support/Casting.h>
-#include <mcld/LD/SectionMap.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/AlignFragment.h>
-#include <mcld/LD/RegionFragment.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/Fragment/AlignFragment.h>
+#include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MemoryArea.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Support/TargetRegistry.h>
+#include <mcld/Fragment/Stub.h>
+#include <mcld/LD/BranchIslandFactory.h>
+#include <mcld/LD/StubFactory.h>
+#include <mcld/Object/ObjectBuilder.h>
+#include <mcld/Fragment/NullFragment.h>
+#include <mcld/LD/LDContext.h>
using namespace mcld;
//===----------------------------------------------------------------------===//
// ARMGNULDBackend
//===----------------------------------------------------------------------===//
-ARMGNULDBackend::ARMGNULDBackend()
- : m_pRelocFactory(NULL),
+ARMGNULDBackend::ARMGNULDBackend(const LinkerConfig& pConfig)
+ : GNULDBackend(pConfig),
+ m_pRelocFactory(NULL),
m_pGOT(NULL),
m_pPLT(NULL),
m_pRelDyn(NULL),
m_pRelPLT(NULL),
m_pDynamic(NULL),
m_pGOTSymbol(NULL),
+ m_pEXIDXStart(NULL),
+ m_pEXIDXEnd(NULL),
m_pEXIDX(NULL),
m_pEXTAB(NULL),
m_pAttributes(NULL) {
@@ -49,25 +62,19 @@
ARMGNULDBackend::~ARMGNULDBackend()
{
- if (NULL != m_pRelocFactory)
- delete m_pRelocFactory;
- if (NULL != m_pGOT)
- delete m_pGOT;
- if (NULL != m_pPLT)
- delete m_pPLT;
- if (NULL != m_pRelDyn)
- delete m_pRelDyn;
- if (NULL != m_pRelPLT)
- delete m_pRelPLT;
- if (NULL != m_pDynamic)
- delete m_pDynamic;
+ delete m_pRelocFactory;
+ delete m_pGOT;
+ delete m_pPLT;
+ delete m_pRelDyn;
+ delete m_pRelPLT;
+ delete m_pDynamic;
}
-bool ARMGNULDBackend::initRelocFactory(const MCLinker& pLinker)
+bool ARMGNULDBackend::initRelocFactory(const FragmentLinker& pLinker)
{
if (NULL == m_pRelocFactory) {
m_pRelocFactory = new ARMRelocationFactory(1024, *this);
- m_pRelocFactory->setLayout(pLinker.getLayout());
+ m_pRelocFactory->setFragmentLinker(pLinker);
}
return true;
}
@@ -78,41 +85,58 @@
return m_pRelocFactory;
}
-bool ARMGNULDBackend::initTargetSectionMap(SectionMap& pSectionMap)
-{
- if (!pSectionMap.push_back(".ARM.exidx", ".ARM.exidx") ||
- !pSectionMap.push_back(".ARM.extab", ".ARM.extab") ||
- !pSectionMap.push_back(".ARM.attributes", ".ARM.attributes"))
- return false;
- return true;
-}
-
-void ARMGNULDBackend::initTargetSections(MCLinker& pLinker)
+void ARMGNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
{
// FIXME: Currently we set exidx and extab to "Exception" and directly emit
// them from input
- m_pEXIDX = &pLinker.getOrCreateOutputSectHdr(".ARM.exidx",
- LDFileFormat::Target,
- llvm::ELF::SHT_ARM_EXIDX,
- llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER,
- bitclass() / 8);
- m_pEXTAB = &pLinker.getOrCreateOutputSectHdr(".ARM.extab",
- LDFileFormat::Target,
- llvm::ELF::SHT_PROGBITS,
- llvm::ELF::SHF_ALLOC,
- 0x1);
- m_pAttributes = &pLinker.getOrCreateOutputSectHdr(".ARM.attributes",
- LDFileFormat::Target,
- llvm::ELF::SHT_ARM_ATTRIBUTES,
- 0x0,
- 0x1);
+ m_pEXIDX = pBuilder.CreateSection(".ARM.exidx",
+ LDFileFormat::Target,
+ llvm::ELF::SHT_ARM_EXIDX,
+ llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER,
+ bitclass() / 8);
+ m_pEXTAB = pBuilder.CreateSection(".ARM.extab",
+ LDFileFormat::Target,
+ llvm::ELF::SHT_PROGBITS,
+ llvm::ELF::SHF_ALLOC,
+ 0x1);
+ m_pAttributes = pBuilder.CreateSection(".ARM.attributes",
+ LDFileFormat::Target,
+ llvm::ELF::SHT_ARM_ATTRIBUTES,
+ 0x0,
+ 0x1);
+
+ if (LinkerConfig::Object != config().codeGenType()) {
+ ELFFileFormat* file_format = getOutputFormat();
+
+ // initialize .got
+ LDSection& got = file_format->getGOT();
+ m_pGOT = new ARMGOT(got);
+
+ // initialize .plt
+ LDSection& plt = file_format->getPLT();
+ m_pPLT = new ARMPLT(plt, *m_pGOT);
+
+ // initialize .rel.plt
+ LDSection& relplt = file_format->getRelPlt();
+ relplt.setLink(&plt);
+ // create SectionData and ARMRelDynSection
+ m_pRelPLT = new OutputRelocSection(pModule,
+ relplt,
+ getRelEntrySize());
+
+ // initialize .rel.dyn
+ LDSection& reldyn = file_format->getRelDyn();
+ m_pRelDyn = new OutputRelocSection(pModule,
+ reldyn,
+ getRelEntrySize());
+ }
}
-void ARMGNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
+void ARMGNULDBackend::initTargetSymbols(FragmentLinker& pLinker)
{
// Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
// same name in input
- m_pGOTSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
+ m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::AsRefered, FragmentLinker::Resolve>(
"_GLOBAL_OFFSET_TABLE_",
false,
ResolveInfo::Object,
@@ -120,25 +144,76 @@
ResolveInfo::Local,
0x0, // size
0x0, // value
- NULL, // FragRef
+ FragmentRef::Null(), // FragRef
ResolveInfo::Hidden);
+
+ FragmentRef* exidx_start = NULL;
+ FragmentRef* exidx_end = NULL;
+ ResolveInfo::Desc desc = ResolveInfo::Undefined;
+ if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size()) {
+ exidx_start = FragmentRef::Create(m_pEXIDX->getSectionData()->front(), 0x0);
+ exidx_end = FragmentRef::Create(m_pEXIDX->getSectionData()->back(), 0x0);
+ desc = ResolveInfo::Define;
+ }
+ else {
+ exidx_start = FragmentRef::Null();
+ exidx_end = FragmentRef::Null();
+ }
+ m_pEXIDXStart =
+ pLinker.defineSymbol<FragmentLinker::Force,
+ FragmentLinker::Resolve>("__exidx_start",
+ false,
+ ResolveInfo::NoType,
+ desc, // ResolveInfo::Desc
+ ResolveInfo::Global,
+ 0x0, // size
+ 0x0, // value
+ exidx_start, // FragRef
+ ResolveInfo::Hidden);
+
+ m_pEXIDXEnd =
+ pLinker.defineSymbol<FragmentLinker::Force,
+ FragmentLinker::Resolve>("__exidx_end",
+ false,
+ ResolveInfo::NoType,
+ desc, //ResolveInfo::Desc
+ ResolveInfo::Global,
+ 0x0, // size
+ 0x0, // value
+ exidx_end, // FragRef
+ ResolveInfo::Hidden);
}
-void ARMGNULDBackend::doPreLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker)
+void ARMGNULDBackend::doPreLayout(FragmentLinker& pLinker)
{
- // when building shared object, the .got section is must.
- if (pOutput.type() == Output::DynObj && (NULL == m_pGOT)) {
- createARMGOT(pLinker, pOutput);
+ // set .got size
+ // when building shared object, the .got section is must
+ if (LinkerConfig::Object != config().codeGenType()) {
+ if (LinkerConfig::DynObj == config().codeGenType() ||
+ m_pGOT->hasGOT1() ||
+ NULL != m_pGOTSymbol) {
+ m_pGOT->finalizeSectionSize();
+ defineGOTSymbol(pLinker);
+ }
+
+ // set .plt size
+ if (m_pPLT->hasPLT1())
+ m_pPLT->finalizeSectionSize();
+
+ // set .rel.dyn size
+ if (!m_pRelDyn->empty())
+ m_pRelDyn->finalizeSectionSize();
+
+ // set .rel.plt size
+ if (!m_pRelPLT->empty())
+ m_pRelPLT->finalizeSectionSize();
}
}
-void ARMGNULDBackend::doPostLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker)
+void ARMGNULDBackend::doPostLayout(Module& pModule,
+ FragmentLinker& pLinker)
{
- const ELFFileFormat *file_format = getOutputFormat(pOutput);
+ const ELFFileFormat *file_format = getOutputFormat();
// apply PLT
if (file_format->hasPLT()) {
@@ -153,7 +228,7 @@
if (file_format->hasGOT()) {
// Since we already have the size of GOT, m_pGOT should not be NULL.
assert(NULL != m_pGOT);
- if (pOutput.type() == Output::DynObj)
+ if (LinkerConfig::DynObj == config().codeGenType())
m_pGOT->applyGOT0(file_format->getDynamic().addr());
else {
// executable file and object file? should fill with zero.
@@ -180,17 +255,11 @@
return *m_pDynamic;
}
-void ARMGNULDBackend::createARMGOT(MCLinker& pLinker, const Output& pOutput)
+void ARMGNULDBackend::defineGOTSymbol(FragmentLinker& pLinker)
{
- // get .got LDSection and create SectionData
- ELFFileFormat* file_format = getOutputFormat(pOutput);
-
- LDSection& got = file_format->getGOT();
- m_pGOT = new ARMGOT(got, pLinker.getOrCreateSectData(got));
-
// define symbol _GLOBAL_OFFSET_TABLE_ when .got create
if (m_pGOTSymbol != NULL) {
- pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
+ pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Unresolve>(
"_GLOBAL_OFFSET_TABLE_",
false,
ResolveInfo::Object,
@@ -198,11 +267,11 @@
ResolveInfo::Local,
0x0, // size
0x0, // value
- pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+ FragmentRef::Create(*(m_pGOT->begin()), 0x0),
ResolveInfo::Hidden);
}
else {
- m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+ m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
"_GLOBAL_OFFSET_TABLE_",
false,
ResolveInfo::Object,
@@ -210,80 +279,44 @@
ResolveInfo::Local,
0x0, // size
0x0, // value
- pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+ FragmentRef::Create(*(m_pGOT->begin()), 0x0),
ResolveInfo::Hidden);
}
}
-void ARMGNULDBackend::createARMPLTandRelPLT(MCLinker& pLinker,
- const Output& pOutput)
-{
- ELFFileFormat* file_format = getOutputFormat(pOutput);
-
- // get .plt and .rel.plt LDSection
- LDSection& plt = file_format->getPLT();
- LDSection& relplt = file_format->getRelPlt();
- // create SectionData and ARMPLT
- m_pPLT = new ARMPLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOT);
- // set info of .rel.plt to .plt
- relplt.setLink(&plt);
- // create SectionData and ARMRelDynSection
- m_pRelPLT = new OutputRelocSection(relplt,
- pLinker.getOrCreateSectData(relplt),
- 8);
-}
-
-void ARMGNULDBackend::createARMRelDyn(MCLinker& pLinker,
- const Output& pOutput)
-{
- ELFFileFormat* file_format = getOutputFormat(pOutput);
-
- // get .rel.dyn LDSection and create SectionData
- LDSection& reldyn = file_format->getRelDyn();
- // create SectionData and ARMRelDynSection
- m_pRelDyn = new OutputRelocSection(reldyn,
- pLinker.getOrCreateSectData(reldyn),
- 8);
-}
-
void ARMGNULDBackend::addCopyReloc(ResolveInfo& pSym)
{
- bool exist;
- Relocation& rel_entry = *m_pRelDyn->getEntry(pSym, false, exist);
+ Relocation& rel_entry = *m_pRelDyn->consumeEntry();
rel_entry.setType(llvm::ELF::R_ARM_COPY);
assert(pSym.outSymbol()->hasFragRef());
rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
rel_entry.setSymInfo(&pSym);
}
-LDSymbol& ARMGNULDBackend::defineSymbolforCopyReloc(MCLinker& pLinker,
- const ResolveInfo& pSym)
+/// defineSymbolForCopyReloc
+/// For a symbol needing copy relocation, define a copy symbol in the BSS
+/// section and all other reference to this symbol should refer to this
+/// copy.
+/// This is executed at scan relocation stage.
+LDSymbol&
+ARMGNULDBackend::defineSymbolforCopyReloc(FragmentLinker& pLinker,
+ const ResolveInfo& pSym)
{
- // For a symbol needing copy relocation, define a copy symbol in the BSS
- // section and all other reference to this symbol should refer to this
- // copy.
-
// get or create corresponding BSS LDSection
LDSection* bss_sect_hdr = NULL;
- if (ResolveInfo::ThreadLocal == pSym.type()) {
- bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
- ".tbss",
- LDFileFormat::BSS,
- llvm::ELF::SHT_NOBITS,
- llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
- }
- else {
- bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
- LDFileFormat::BSS,
- llvm::ELF::SHT_NOBITS,
- llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
- }
+ ELFFileFormat* file_format = getOutputFormat();
+ if (ResolveInfo::ThreadLocal == pSym.type())
+ bss_sect_hdr = &file_format->getTBSS();
+ else
+ bss_sect_hdr = &file_format->getBSS();
// get or create corresponding BSS SectionData
- assert(NULL != bss_sect_hdr);
- SectionData& bss_section = pLinker.getOrCreateSectData(
- *bss_sect_hdr);
+ SectionData* bss_data = NULL;
+ if (bss_sect_hdr->hasSectionData())
+ bss_data = bss_sect_hdr->getSectionData();
+ else
+ bss_data = IRBuilder::CreateSectionData(*bss_sect_hdr);
// Determine the alignment by the symbol value
// FIXME: here we use the largest alignment
@@ -291,9 +324,9 @@
// allocate space in BSS for the copy symbol
Fragment* frag = new FillFragment(0x0, 1, pSym.size());
- uint64_t size = pLinker.getLayout().appendFragment(*frag,
- bss_section,
- addralign);
+ uint64_t size = ObjectBuilder::AppendFragment(*frag,
+ *bss_data,
+ addralign);
bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
// change symbol binding to Global if it's a weak symbol
@@ -302,7 +335,7 @@
binding = ResolveInfo::Global;
// Define the copy symbol in the bss section and resolve it
- LDSymbol* cpy_sym = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+ LDSymbol* cpy_sym = pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
pSym.name(),
false,
(ResolveInfo::Type)pSym.type(),
@@ -310,7 +343,7 @@
binding,
pSym.size(), // size
0x0, // value
- pLinker.getLayout().getFragmentRef(*frag, 0x0),
+ FragmentRef::Create(*frag, 0x0),
(ResolveInfo::Visibility)pSym.other());
return *cpy_sym;
@@ -319,11 +352,10 @@
/// checkValidReloc - When we attempt to generate a dynamic relocation for
/// ouput file, check if the relocation is supported by dynamic linker.
void ARMGNULDBackend::checkValidReloc(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
- const Output& pOutput) const
+ const FragmentLinker& pLinker) const
{
- // If not building a PIC object, no relocation type is invalid
- if (!isOutputPIC(pOutput, pLDInfo))
+ // If not PIC object, no relocation type is invalid
+ if (!pLinker.isOutputPIC())
return;
switch(pReloc.type()) {
@@ -346,28 +378,12 @@
}
}
-void ARMGNULDBackend::updateAddend(Relocation& pReloc,
- const LDSymbol& pInputSym,
- const Layout& pLayout) const
-{
- // Update value keep in addend if we meet a section symbol
- if (pReloc.symInfo()->type() == ResolveInfo::Section) {
- pReloc.setAddend(pLayout.getOutputOffset(
- *pInputSym.fragRef()) + pReloc.addend());
- }
-}
-
void ARMGNULDBackend::scanLocalReloc(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput)
+ FragmentLinker& pLinker)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
- updateAddend(pReloc, pInputSym, pLinker.getLayout());
-
switch(pReloc.type()){
// Set R_ARM_TARGET1 to R_ARM_ABS32
@@ -381,10 +397,7 @@
// If buiding PIC object (shared library or PIC executable),
// a dynamic relocations with RELATIVE type to this location is needed.
// Reserve an entry in .rel.dyn
- if (isOutputPIC(pOutput, pLDInfo)) {
- //create .rel.dyn section if not exist
- if (NULL == m_pRelDyn)
- createARMRelDyn(pLinker, pOutput);
+ if (pLinker.isOutputPIC()) {
m_pRelDyn->reserveEntry(*m_pRelocFactory);
// set Rel bit
rsym->setReserved(rsym->reserved() | ReserveRel);
@@ -402,7 +415,7 @@
case llvm::ELF::R_ARM_THM_MOVW_ABS_NC:
case llvm::ELF::R_ARM_THM_MOVT_ABS: {
// PIC code should not contain these kinds of relocation
- if (isOutputPIC(pOutput, pLDInfo)) {
+ if (pLinker.isOutputPIC()) {
error(diag::non_pic_relocation) << (int)pReloc.type()
<< pReloc.symInfo()->name();
}
@@ -410,9 +423,7 @@
}
case llvm::ELF::R_ARM_GOTOFF32:
case llvm::ELF::R_ARM_GOTOFF12: {
- // A GOT section is needed
- if (NULL == m_pGOT)
- createARMGOT(pLinker, pOutput);
+ // FIXME: A GOT section is needed
return;
}
@@ -427,16 +438,12 @@
// return if we already create GOT for this symbol
if (rsym->reserved() & (ReserveGOT | GOTRel))
return;
- if (NULL == m_pGOT)
- createARMGOT(pLinker, pOutput);
- m_pGOT->reserveEntry();
+ m_pGOT->reserveGOT();
// If building PIC object, a dynamic relocation with
// type RELATIVE is needed to relocate this GOT entry.
// Reserve an entry in .rel.dyn
- if (isOutputPIC(pOutput, pLDInfo)) {
+ if (pLinker.isOutputPIC()) {
// create .rel.dyn section if not exist
- if (NULL == m_pRelDyn)
- createARMRelDyn(pLinker, pOutput);
m_pRelDyn->reserveEntry(*m_pRelocFactory);
// set GOTRel bit
rsym->setReserved(rsym->reserved() | 0x4u);
@@ -471,10 +478,7 @@
}
void ARMGNULDBackend::scanGlobalReloc(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput)
+ FragmentLinker& pLinker)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
@@ -500,15 +504,9 @@
case llvm::ELF::R_ARM_ABS32_NOI: {
// Absolute relocation type, symbol may needs PLT entry or
// dynamic relocation entry
- if (symbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
+ if (symbolNeedsPLT(pLinker, *rsym)) {
// create plt for this symbol if it does not have one
if (!(rsym->reserved() & ReservePLT)){
- // Create .got section if it doesn't exist
- if (NULL == m_pGOT)
- createARMGOT(pLinker, pOutput);
- // create .plt and .rel.plt if not exist
- if (NULL == m_pPLT)
- createARMPLTandRelPLT(pLinker, pOutput);
// Symbol needs PLT entry, we need to reserve a PLT entry
// and the corresponding GOT and dynamic relocation entry
// in .got and .rel.plt. (GOT entry will be reserved simultaneously
@@ -520,20 +518,16 @@
}
}
- if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
- pLDInfo, pOutput, true)) {
+ if (symbolNeedsDynRel(
+ pLinker, *rsym, (rsym->reserved() & ReservePLT), true)) {
// symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
- // create .rel.dyn section if not exist
- if (NULL == m_pRelDyn)
- createARMRelDyn(pLinker, pOutput);
m_pRelDyn->reserveEntry(*m_pRelocFactory);
- if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
- pOutput)) {
+ if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
addCopyReloc(*cpy_sym.resolveInfo());
}
else {
- checkValidReloc(pReloc, pLDInfo, pOutput);
+ checkValidReloc(pReloc, pLinker);
// set Rel bit
rsym->setReserved(rsym->reserved() | ReserveRel);
}
@@ -543,9 +537,7 @@
case llvm::ELF::R_ARM_GOTOFF32:
case llvm::ELF::R_ARM_GOTOFF12: {
- // A GOT section is needed
- if (NULL == m_pGOT)
- createARMGOT(pLinker, pOutput);
+ // FIXME: A GOT section is needed
return;
}
@@ -601,20 +593,16 @@
case llvm::ELF::R_ARM_MOVT_BREL:
case llvm::ELF::R_ARM_MOVW_BREL: {
// Relative addressing relocation, may needs dynamic relocation
- if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
- pLDInfo, pOutput, false)) {
+ if (symbolNeedsDynRel(
+ pLinker, *rsym, (rsym->reserved() & ReservePLT), false)) {
// symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
- // create .rel.dyn section if not exist
- if (NULL == m_pRelDyn)
- createARMRelDyn(pLinker, pOutput);
m_pRelDyn->reserveEntry(*m_pRelocFactory);
- if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
- pOutput)) {
+ if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
addCopyReloc(*cpy_sym.resolveInfo());
}
else {
- checkValidReloc(pReloc, pLDInfo, pOutput);
+ checkValidReloc(pReloc, pLinker);
// set Rel bit
rsym->setReserved(rsym->reserved() | ReserveRel);
}
@@ -640,20 +628,17 @@
if (rsym->reserved() & ReservePLT)
return;
+ // if the symbol's value can be decided at link time, then no need plt
+ if (symbolFinalValueIsKnown(pLinker, *rsym))
+ return;
+
// if symbol is defined in the ouput file and it's not
// preemptible, no need plt
if (rsym->isDefine() && !rsym->isDyn() &&
- !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) {
+ !isSymbolPreemptible(*rsym)) {
return;
}
- // Create .got section if it doesn't exist
- if (NULL == m_pGOT)
- createARMGOT(pLinker, pOutput);
-
- // create .plt and .rel.plt if not exist
- if (NULL == m_pPLT)
- createARMPLTandRelPLT(pLinker, pOutput);
// Symbol needs PLT entry, we need to reserve a PLT entry
// and the corresponding GOT and dynamic relocation entry
// in .got and .rel.plt. (GOT entry will be reserved simultaneously
@@ -677,16 +662,10 @@
// return if we already create GOT for this symbol
if (rsym->reserved() & (ReserveGOT | GOTRel))
return;
- if (NULL == m_pGOT)
- createARMGOT(pLinker, pOutput);
- m_pGOT->reserveEntry();
- // If building shared object or the symbol is undefined, a dynamic
- // relocation is needed to relocate this GOT entry. Reserve an
- // entry in .rel.dyn
- if (Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
- // create .rel.dyn section if not exist
- if (NULL == m_pRelDyn)
- createARMRelDyn(pLinker, pOutput);
+ m_pGOT->reserveGOT();
+ // if the symbol cannot be fully resolved at link time, then we need a
+ // dynamic relocation
+ if (!symbolFinalValueIsKnown(pLinker, *rsym)) {
m_pRelDyn->reserveEntry(*m_pRelocFactory);
// set GOTRel bit
rsym->setReserved(rsym->reserved() | GOTRel);
@@ -713,56 +692,47 @@
}
void ARMGNULDBackend::scanRelocation(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput,
+ FragmentLinker& pLinker,
+ Module& pModule,
const LDSection& pSection)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
- assert(NULL != pSection.getLink());
- if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) {
- if (rsym->isLocal()) {
- updateAddend(pReloc, pInputSym, pLinker.getLayout());
- }
+ pReloc.updateAddend();
+ if (0 == (pSection.flag() & llvm::ELF::SHF_ALLOC))
return;
- }
// Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
// entries should be created.
- // FIXME: Below judgements concern only .so is generated as output
// FIXME: Below judgements concern nothing about TLS related relocation
- // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got section
- // is needed
- if (NULL == m_pGOT && NULL != m_pGOTSymbol) {
- if (rsym == m_pGOTSymbol->resolveInfo()) {
- createARMGOT(pLinker, pOutput);
- }
- }
-
// rsym is local
if (rsym->isLocal())
- scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
+ scanLocalReloc(pReloc, pLinker);
// rsym is external
else
- scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
+ scanGlobalReloc(pReloc, pLinker);
+ // check if we shoule issue undefined reference for the relocation target
+ // symbol
+ if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak())
+ fatal(diag::undefined_reference) << rsym->name();
+
+ if ((rsym->reserved() & ReserveRel) != 0x0) {
+ // set hasTextRelSection if needed
+ checkAndSetHasTextRel(pSection);
+ }
}
-uint64_t ARMGNULDBackend::emitSectionData(const Output& pOutput,
- const LDSection& pSection,
- const MCLDInfo& pInfo,
- const Layout& pLayout,
+uint64_t ARMGNULDBackend::emitSectionData(const LDSection& pSection,
MemoryRegion& pRegion) const
{
assert(pRegion.size() && "Size of MemoryRegion is zero!");
- const ELFFileFormat* file_format = getOutputFormat(pOutput);
+ const ELFFileFormat* file_format = getOutputFormat();
if (&pSection == m_pAttributes ||
&pSection == m_pEXIDX ||
@@ -773,8 +743,19 @@
SectionData::const_iterator frag_iter, frag_end = sect_data->end();
uint8_t* out_offset = pRegion.start();
for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
- size_t size = computeFragmentSize(pLayout, *frag_iter);
+ size_t size = frag_iter->size();
switch(frag_iter->getKind()) {
+ case Fragment::Fillment: {
+ const FillFragment& fill_frag =
+ llvm::cast<FillFragment>(*frag_iter);
+ if (0 == fill_frag.getValueSize()) {
+ // virtual fillment, ignore it.
+ break;
+ }
+
+ memset(out_offset, fill_frag.getValue(), fill_frag.size());
+ break;
+ }
case Fragment::Region: {
const RegionFragment& region_frag =
llvm::cast<RegionFragment>(*frag_iter);
@@ -796,6 +777,10 @@
} // end switch
break;
}
+ case Fragment::Null: {
+ assert(0x0 == size);
+ break;
+ }
default:
llvm::report_fatal_error("unsupported fragment type.\n");
break;
@@ -823,48 +808,63 @@
}
/// finalizeSymbol - finalize the symbol value
-bool ARMGNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
+bool ARMGNULDBackend::finalizeTargetSymbols(FragmentLinker& pLinker)
{
+ if (NULL != m_pEXIDXStart) {
+ if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size())
+ m_pEXIDXStart->setValue(m_pEXIDX->addr());
+ }
+
+ if (NULL != m_pEXIDXEnd) {
+ if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size())
+ m_pEXIDXEnd->setValue(m_pEXIDX->addr() + m_pEXIDX->size());
+ }
return true;
}
-bool ARMGNULDBackend::readSection(Input& pInput,
- MCLinker& pLinker,
- LDSection& pInputSectHdr)
+bool ARMGNULDBackend::mergeSection(Module& pModule, LDSection& pSection)
{
- LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(),
- pInputSectHdr.kind(),
- pInputSectHdr.type(),
- pInputSectHdr.flag());
- // FIXME: (Luba)
- // Handle ARM attributes in the right way.
- // In current milestone, MCLinker goes through the shortcut.
- // It reads input's ARM attributes and copies the first ARM attributes
- // into the output file. The correct way is merge these sections, not
- // just copy.
- if ((0 == out_sect.name().compare(".ARM.attributes")) &&
- (0 != out_sect.size()))
- return true;
+ switch (pSection.type()) {
+ case llvm::ELF::SHT_ARM_ATTRIBUTES: {
+ // FIXME: (Luba)
+ // Handle ARM attributes in the right way.
+ // In current milestone, FragmentLinker goes through the shortcut.
+ // It reads input's ARM attributes and copies the first ARM attributes
+ // into the output file. The correct way is merge these sections, not
+ // just copy.
+ if (0 != m_pAttributes->size())
+ return true;
- MemoryRegion* region = pInput.memArea()->request(
- pInput.fileOffset() + pInputSectHdr.offset(), pInputSectHdr.size());
+ // First time we meet a ARM attributes section.
+ SectionData* sd = IRBuilder::CreateSectionData(*m_pAttributes);
+ ObjectBuilder::MoveSectionData(*pSection.getSectionData(), *sd);
+ return true;
+ }
+ default: {
+ ObjectBuilder builder(config(), pModule);
+ return builder.MergeSection(pSection);
+ }
+ } // end of switch
+ return true;
+}
- SectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr);
-
+bool ARMGNULDBackend::readSection(Input& pInput, SectionData& pSD)
+{
Fragment* frag = NULL;
+ uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
+ uint32_t size = pSD.getSection().size();
+
+ MemoryRegion* region = pInput.memArea()->request(offset, size);
if (NULL == region) {
// If the input section's size is zero, we got a NULL region.
// use a virtual fill fragment
frag = new FillFragment(0x0, 0, 0);
}
- else
+ else {
frag = new RegionFragment(*region);
+ }
- uint64_t size = pLinker.getLayout().appendFragment(*frag,
- sect_data,
- pInputSectHdr.align());
-
- out_sect.setSize(out_sect.size() + size);
+ ObjectBuilder::AppendFragment(*frag, pSD);
return true;
}
@@ -917,14 +917,12 @@
}
unsigned int
-ARMGNULDBackend::getTargetSectionOrder(const Output& pOutput,
- const LDSection& pSectHdr,
- const MCLDInfo& pInfo) const
+ARMGNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
{
- const ELFFileFormat* file_format = getOutputFormat(pOutput);
+ const ELFFileFormat* file_format = getOutputFormat();
if (&pSectHdr == &file_format->getGOT()) {
- if (pInfo.options().hasNow())
+ if (config().options().hasNow())
return SHO_RELRO_LAST;
return SHO_DATA;
}
@@ -940,16 +938,148 @@
return SHO_UNDEFINED;
}
+/// doRelax
+bool ARMGNULDBackend::doRelax(Module& pModule, FragmentLinker& pLinker, bool& pFinished)
+{
+ assert(NULL != getStubFactory() && NULL != getBRIslandFactory());
+
+ bool isRelaxed = false;
+ ELFFileFormat* file_format = getOutputFormat();
+ // check branch relocs and create the related stubs if needed
+ Module::obj_iterator input, inEnd = pModule.obj_end();
+ for (input = pModule.obj_begin(); input != inEnd; ++input) {
+ LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
+ for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
+ if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
+ continue;
+ RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
+ for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
+ Relocation* relocation = llvm::cast<Relocation>(reloc);
+
+ switch (relocation->type()) {
+ case llvm::ELF::R_ARM_CALL:
+ case llvm::ELF::R_ARM_JUMP24:
+ case llvm::ELF::R_ARM_PLT32:
+ case llvm::ELF::R_ARM_THM_CALL:
+ case llvm::ELF::R_ARM_THM_XPC22:
+ case llvm::ELF::R_ARM_THM_JUMP24:
+ case llvm::ELF::R_ARM_THM_JUMP19:
+ case llvm::ELF::R_ARM_V4BX: {
+ // calculate the possible symbol value
+ uint64_t sym_value = 0x0;
+ LDSymbol* symbol = relocation->symInfo()->outSymbol();
+ if (symbol->hasFragRef()) {
+ uint64_t value = symbol->fragRef()->getOutputOffset();
+ uint64_t addr =
+ symbol->fragRef()->frag()->getParent()->getSection().addr();
+ sym_value = addr + value;
+ }
+ if (relocation->symInfo()->isGlobal() &&
+ (relocation->symInfo()->reserved() & ReservePLT) != 0x0) {
+ // FIXME: we need to find out the address of the specific plt entry
+ assert(file_format->hasPLT());
+ sym_value = file_format->getPLT().addr();
+ }
+
+ Stub* stub = getStubFactory()->create(*relocation, // relocation
+ sym_value, // symbol value
+ pLinker,
+ *getRelocFactory(),
+ *getBRIslandFactory());
+ if (NULL != stub) {
+ assert(NULL != stub->symInfo());
+ // increase the size of .symtab and .strtab
+ LDSection& symtab = file_format->getSymTab();
+ LDSection& strtab = file_format->getStrTab();
+ if (32 == bitclass())
+ symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
+ else
+ symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf64_Sym));
+ strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1);
+
+ isRelaxed = true;
+ }
+ break;
+ }
+ default:
+ break;
+ } // end of switch
+
+ } // for all relocations
+ } // for all relocation section
+ } // for all inputs
+
+ // find the first fragment w/ invalid offset due to stub insertion
+ Fragment* invalid = NULL;
+ pFinished = true;
+ for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(),
+ island_end = getBRIslandFactory()->end(); island != island_end; ++island) {
+ if ((*island).end() == file_format->getText().getSectionData()->end())
+ break;
+
+ Fragment* exit = (*island).end();
+ if (((*island).offset() + (*island).size()) > exit->getOffset()) {
+ invalid = exit;
+ pFinished = false;
+ break;
+ }
+ }
+
+ // reset the offset of invalid fragments
+ while (NULL != invalid) {
+ invalid->setOffset(invalid->getPrevNode()->getOffset() +
+ invalid->getPrevNode()->size());
+ invalid = invalid->getNextNode();
+ }
+
+ // reset the size of .text
+ if (isRelaxed) {
+ file_format->getText().setSize(
+ file_format->getText().getSectionData()->back().getOffset() +
+ file_format->getText().getSectionData()->back().size());
+ }
+ return isRelaxed;
+}
+
+/// initTargetStubs
+bool ARMGNULDBackend::initTargetStubs(FragmentLinker& pLinker)
+{
+ if (NULL != getStubFactory()) {
+ getStubFactory()->addPrototype(new ARMToARMStub(pLinker.isOutputPIC()));
+ getStubFactory()->addPrototype(new ARMToTHMStub(pLinker.isOutputPIC()));
+ getStubFactory()->addPrototype(new THMToTHMStub(pLinker.isOutputPIC()));
+ getStubFactory()->addPrototype(new THMToARMStub(pLinker.isOutputPIC()));
+ return true;
+ }
+ return false;
+}
+
+/// doCreateProgramHdrs - backend can implement this function to create the
+/// target-dependent segments
+void ARMGNULDBackend::doCreateProgramHdrs(Module& pModule,
+ const FragmentLinker& pLinker)
+{
+ if (NULL != m_pEXIDX && 0x0 != m_pEXIDX->size()) {
+ // make PT_ARM_EXIDX
+ // FIXME: once we have a patch for llvm/Support/ELF.h, we can refine this
+ enum {
+ PT_ARM_EXIDX = 0x70000001
+ };
+ ELFSegment* exidx_seg = elfSegmentTable().produce(PT_ARM_EXIDX,
+ llvm::ELF::PF_R);
+ exidx_seg->addSection(m_pEXIDX);
+ }
+}
+
namespace mcld {
//===----------------------------------------------------------------------===//
/// createARMLDBackend - the help funtion to create corresponding ARMLDBackend
///
TargetLDBackend* createARMLDBackend(const llvm::Target& pTarget,
- const std::string& pTriple)
+ const LinkerConfig& pConfig)
{
- Triple theTriple(pTriple);
- if (theTriple.isOSDarwin()) {
+ if (pConfig.triple().isOSDarwin()) {
assert(0 && "MachO linker is not supported yet");
/**
return new ARMMachOLDBackend(createARMMachOArchiveReader,
@@ -957,7 +1087,7 @@
createARMMachOObjectWriter);
**/
}
- if (theTriple.isOSWindows()) {
+ if (pConfig.triple().isOSWindows()) {
assert(0 && "COFF linker is not supported yet");
/**
return new ARMCOFFLDBackend(createARMCOFFArchiveReader,
@@ -965,14 +1095,15 @@
createARMCOFFObjectWriter);
**/
}
- return new ARMGNULDBackend();
+ return new ARMGNULDBackend(pConfig);
}
} // namespace of mcld
-//=============================
+//===----------------------------------------------------------------------===//
// Force static initialization.
-extern "C" void LLVMInitializeARMLDBackend() {
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeARMLDBackend() {
// Register the linker backend
mcld::TargetRegistry::RegisterTargetLDBackend(TheARMTarget, createARMLDBackend);
mcld::TargetRegistry::RegisterTargetLDBackend(TheThumbTarget, createARMLDBackend);
diff --git a/lib/Target/ARM/ARMLDBackend.h b/lib/Target/ARM/ARMLDBackend.h
index 981228e..6cf531b 100644
--- a/lib/Target/ARM/ARMLDBackend.h
+++ b/lib/Target/ARM/ARMLDBackend.h
@@ -18,20 +18,29 @@
namespace mcld {
-class MCLDInfo;
-class MCLinker;
-class Output;
+class LinkerConfig;
+class FragmentLinker;
class SectionMap;
-
//===----------------------------------------------------------------------===//
/// ARMGNULDBackend - linker backend of ARM target of GNU ELF format
///
class ARMGNULDBackend : public GNULDBackend
{
public:
- ARMGNULDBackend();
+ // max branch offsets for ARM, THUMB, and THUMB2
+ // @ref gold/arm.cc:99
+ static const int32_t ARM_MAX_FWD_BRANCH_OFFSET = ((((1 << 23) - 1) << 2) + 8);
+ static const int32_t ARM_MAX_BWD_BRANCH_OFFSET = ((-((1 << 23) << 2)) + 8);
+ static const int32_t THM_MAX_FWD_BRANCH_OFFSET = ((1 << 22) -2 + 4);
+ static const int32_t THM_MAX_BWD_BRANCH_OFFSET = (-(1 << 22) + 4);
+ static const int32_t THM2_MAX_FWD_BRANCH_OFFSET = (((1 << 24) - 2) + 4);
+ static const int32_t THM2_MAX_BWD_BRANCH_OFFSET = (-(1 << 24) + 4);
+
+public:
+ ARMGNULDBackend(const LinkerConfig& pConfig);
~ARMGNULDBackend();
+
public:
typedef std::vector<llvm::ELF::Elf32_Dyn*> ELF32DynList;
@@ -79,17 +88,14 @@
};
public:
- /// initTargetSectionMap - initialize target dependent section mapping
- bool initTargetSectionMap(SectionMap& pSectionMap);
-
/// initTargetSections - initialize target dependent sections in output.
- void initTargetSections(MCLinker& pLinker);
+ void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
/// initTargetSymbols - initialize target dependent symbols in output.
- void initTargetSymbols(MCLinker& pLinker, const Output& pOutput);
+ void initTargetSymbols(FragmentLinker& pLinker);
/// initRelocFactory - create and initialize RelocationFactory
- bool initRelocFactory(const MCLinker& pLinker);
+ bool initRelocFactory(const FragmentLinker& pLinker);
/// getRelocFactory
RelocationFactory* getRelocFactory();
@@ -101,10 +107,8 @@
/// - PLT entry (for .plt section)
/// - dynamin relocation entries (for .rel.plt and .rel.dyn sections)
void scanRelocation(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput,
+ FragmentLinker& pLinker,
+ Module& pModule,
const LDSection& pSection);
uint32_t machine() const
@@ -132,14 +136,10 @@
{ return 0x8000; }
/// doPreLayout - Backend can do any needed modification before layout
- void doPreLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker);
+ void doPreLayout(FragmentLinker& pLinker);
/// doPostLayout -Backend can do any needed modification after layout
- void doPostLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker);
+ void doPostLayout(Module& pModule, FragmentLinker& pLinker);
/// dynamic - the dynamic section of the target machine.
/// Use co-variant return type to return its own dynamic section.
@@ -161,16 +161,11 @@
/// - backend can maintain its own map<LDSection, table> to get the table
/// from given LDSection.
///
- /// @param pOutput - the output file
/// @param pSection - the given LDSection
- /// @param pInfo - all options in the command line.
- /// @param pLayout - for comouting the size of fragment
+ /// @param pConfig - all options in the command line.
/// @param pRegion - the region to write out data
/// @return the size of the table in the file.
- uint64_t emitSectionData(const Output& pOutput,
- const LDSection& pSection,
- const MCLDInfo& pInfo,
- const Layout& pLayout,
+ uint64_t emitSectionData(const LDSection& pSection,
MemoryRegion& pRegion) const;
ARMGOT& getGOT();
@@ -190,34 +185,24 @@
const OutputRelocSection& getRelPLT() const;
/// getTargetSectionOrder - compute the layout order of ARM target sections
- unsigned int getTargetSectionOrder(const Output& pOutput,
- const LDSection& pSectHdr,
- const MCLDInfo& pInfo) const;
+ unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
/// finalizeTargetSymbols - finalize the symbol value
- bool finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput);
+ bool finalizeTargetSymbols(FragmentLinker& pLinker);
+
+ /// mergeSection - merge target dependent sections
+ bool mergeSection(Module& pModule, LDSection& pSection);
/// readSection - read target dependent sections
- bool readSection(Input& pInput,
- MCLinker& pLinker,
- LDSection& pInputSectHdr);
+ bool readSection(Input& pInput, SectionData& pSD);
private:
- void scanLocalReloc(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput);
+ void scanLocalReloc(Relocation& pReloc, FragmentLinker& pLinker);
- void scanGlobalReloc(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput);
+ void scanGlobalReloc(Relocation& pReloc, FragmentLinker& pLinker);
void checkValidReloc(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
- const Output& pOutput) const;
+ const FragmentLinker& pLinker) const;
/// addCopyReloc - add a copy relocation into .rel.dyn for pSym
/// @param pSym - A resolved copy symbol that defined in BSS section
@@ -226,25 +211,39 @@
/// defineSymbolforCopyReloc - allocate a space in BSS section and
/// and force define the copy of pSym to BSS section
/// @return the output LDSymbol of the copy symbol
- LDSymbol& defineSymbolforCopyReloc(MCLinker& pLinker,
+ LDSymbol& defineSymbolforCopyReloc(FragmentLinker& pLinker,
const ResolveInfo& pSym);
- /// updateAddend - update addend value of the relocation if the
- /// the target symbol is a section symbol. Addend is the offset
- /// in the section. This value should be updated after section
- /// merged.
- void updateAddend(Relocation& pReloc,
- const LDSymbol& pInputSym,
- const Layout& pLayout) const;
+ void defineGOTSymbol(FragmentLinker& pLinker);
- void createARMGOT(MCLinker& pLinker, const Output& pOutput);
+ /// maxBranchOffset
+ /// FIXME: if we can handle arm attributes, we may refine this!
+ uint64_t maxBranchOffset() { return THM_MAX_FWD_BRANCH_OFFSET; }
- /// createARMPLTandRelPLT - create PLT and RELPLT sections.
- /// Because in ELF sh_info in .rel.plt is the shndx of .plt, these two
- /// sections should be create together.
- void createARMPLTandRelPLT(MCLinker& pLinker, const Output& pOutput);
+ /// mayRelax - Backends should override this function if they need relaxation
+ bool mayRelax() { return true; }
- void createARMRelDyn(MCLinker& pLinker, const Output& pOutput);
+ /// doRelax - Backend can orevride this function to add its relaxation
+ /// implementation. Return true if the output (e.g., .text) is "relaxed"
+ /// (i.e. layout is changed), and set pFinished to true if everything is fit,
+ /// otherwise set it to false.
+ bool doRelax(Module& pModule, FragmentLinker& pLinker, bool& pFinished);
+
+ /// initTargetStubs
+ bool initTargetStubs(FragmentLinker& pLinker);
+
+ /// getRelEntrySize - the size in BYTE of rel type relocation
+ size_t getRelEntrySize()
+ { return 8; }
+
+ /// getRelEntrySize - the size in BYTE of rela type relocation
+ size_t getRelaEntrySize()
+ { assert(0 && "ARM backend with Rela type relocation\n"); return 12; }
+
+ /// doCreateProgramHdrs - backend can implement this function to create the
+ /// target-dependent segments
+ virtual void doCreateProgramHdrs(Module& pModule,
+ const FragmentLinker& pLinker);
private:
RelocationFactory* m_pRelocFactory;
@@ -257,6 +256,8 @@
ARMELFDynamic* m_pDynamic;
LDSymbol* m_pGOTSymbol;
+ LDSymbol* m_pEXIDXStart;
+ LDSymbol* m_pEXIDXEnd;
// variable name : ELF
LDSection* m_pEXIDX; // .ARM.exidx
diff --git a/lib/Target/ARM/ARMMCLinker.cpp b/lib/Target/ARM/ARMMCLinker.cpp
new file mode 100644
index 0000000..cc9486e
--- /dev/null
+++ b/lib/Target/ARM/ARMMCLinker.cpp
@@ -0,0 +1,50 @@
+//===- ARMMCLinker.cpp ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ARMELFMCLinker.h"
+
+#include "ARM.h"
+#include <llvm/ADT/Triple.h>
+#include <mcld/Module.h>
+#include <mcld/Support/TargetRegistry.h>
+
+using namespace mcld;
+
+namespace mcld {
+//===----------------------------------------------------------------------===//
+// createARMMCLinker - the help function to create corresponding ARMMCLinker
+//===----------------------------------------------------------------------===//
+MCLinker* createARMMCLinker(const std::string& pTriple,
+ LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ MemoryArea& pOutput)
+{
+ Triple theTriple(pTriple);
+ if (theTriple.isOSDarwin()) {
+ assert(0 && "MachO linker has not supported yet");
+ return NULL;
+ }
+ if (theTriple.isOSWindows()) {
+ assert(0 && "COFF linker has not supported yet");
+ return NULL;
+ }
+
+ return new ARMELFMCLinker(pConfig, pModule, pOutput);
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// ARMMCLinker
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeARMMCLinker() {
+ // Register the linker frontend
+ mcld::TargetRegistry::RegisterMCLinker(TheARMTarget, createARMMCLinker);
+ mcld::TargetRegistry::RegisterMCLinker(TheThumbTarget, createARMMCLinker);
+}
+
diff --git a/lib/Target/ARM/ARMPLT.cpp b/lib/Target/ARM/ARMPLT.cpp
index c9bc333..a5f4733 100644
--- a/lib/Target/ARM/ARMPLT.cpp
+++ b/lib/Target/ARM/ARMPLT.cpp
@@ -13,6 +13,7 @@
#include <llvm/Support/Casting.h>
+#include <mcld/LD/LDSection.h>
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/MsgHandling.h>
@@ -36,106 +37,73 @@
using namespace mcld;
-ARMPLT0::ARMPLT0(SectionData* pParent)
- : PLTEntry(sizeof(arm_plt0), pParent) {}
+ARMPLT0::ARMPLT0(SectionData& pParent)
+ : PLT::Entry(sizeof(arm_plt0), pParent) {}
-ARMPLT1::ARMPLT1(SectionData* pParent)
- : PLTEntry(sizeof(arm_plt1), pParent) {}
+ARMPLT1::ARMPLT1(SectionData& pParent)
+ : PLT::Entry(sizeof(arm_plt1), pParent) {}
//===----------------------------------------------------------------------===//
// ARMPLT
ARMPLT::ARMPLT(LDSection& pSection,
- SectionData& pSectionData,
ARMGOT &pGOTPLT)
- : PLT(pSection, pSectionData), m_GOT(pGOTPLT), m_PLTEntryIterator() {
- ARMPLT0* plt0_entry = new ARMPLT0(&m_SectionData);
-
- m_Section.setSize(m_Section.size() + plt0_entry->getEntrySize());
-
- m_PLTEntryIterator = pSectionData.begin();
+ : PLT(pSection), m_GOT(pGOTPLT), m_PLTEntryIterator() {
+ new ARMPLT0(*m_SectionData);
+ m_PLTEntryIterator = m_SectionData->begin();
}
ARMPLT::~ARMPLT()
{
}
+bool ARMPLT::hasPLT1() const
+{
+ return (m_SectionData->size() > 1);
+}
+
+void ARMPLT::finalizeSectionSize()
+{
+ uint64_t size = (m_SectionData->size() - 1) * sizeof(arm_plt1) +
+ sizeof(arm_plt0);
+ m_Section.setSize(size);
+
+ uint32_t offset = 0;
+ SectionData::iterator frag, fragEnd = m_SectionData->end();
+ for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) {
+ frag->setOffset(offset);
+ offset += frag->size();
+ }
+}
+
void ARMPLT::reserveEntry(size_t pNum)
{
ARMPLT1* plt1_entry = 0;
for (size_t i = 0; i < pNum; ++i) {
- plt1_entry = new (std::nothrow) ARMPLT1(&m_SectionData);
+ plt1_entry = new (std::nothrow) ARMPLT1(*m_SectionData);
if (!plt1_entry)
fatal(diag::fail_allocate_memory_plt);
- m_Section.setSize(m_Section.size() + plt1_entry->getEntrySize());
-
- m_GOT.reserveGOTPLTEntry();
+ m_GOT.reserveGOTPLT();
}
}
-PLTEntry* ARMPLT::getPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
+ARMPLT1* ARMPLT::consume()
{
- ARMPLT1 *&PLTEntry = m_PLTEntryMap[&pSymbol];
+ ++m_PLTEntryIterator;
+ assert(m_PLTEntryIterator != m_SectionData->end() &&
+ "The number of PLT Entries and ResolveInfo doesn't match");
- pExist = 1;
-
- if (!PLTEntry) {
- GOTEntry *&GOTPLTEntry = m_GOT.lookupGOTPLTMap(pSymbol);
- assert(!GOTPLTEntry && "PLT entry and got.plt entry doesn't match!");
-
- pExist = 0;
-
- // This will skip PLT0.
- ++m_PLTEntryIterator;
- assert(m_PLTEntryIterator != m_SectionData.end() &&
- "The number of PLT Entries and ResolveInfo doesn't match");
-
- ARMGOT::iterator got_it = m_GOT.getNextGOTPLTEntry();
- assert(got_it != m_GOT.getGOTPLTEnd() && "The number of GOTPLT and PLT doesn't match");
-
- PLTEntry = llvm::cast<ARMPLT1>(&(*m_PLTEntryIterator));
- GOTPLTEntry = llvm::cast<GOTEntry>(&(*got_it));
- }
-
- return PLTEntry;
-}
-
-GOTEntry* ARMPLT::getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
-{
- GOTEntry *&GOTPLTEntry = m_GOT.lookupGOTPLTMap(pSymbol);
-
- pExist = 1;
-
- if (!GOTPLTEntry) {
- ARMPLT1 *&PLTEntry = m_PLTEntryMap[&pSymbol];
- assert(!PLTEntry && "PLT entry and got.plt entry doesn't match!");
-
- pExist = 0;
-
- // This will skip PLT0.
- ++m_PLTEntryIterator;
- assert(m_PLTEntryIterator != m_SectionData.end() &&
- "The number of PLT Entries and ResolveInfo doesn't match");
-
- ARMGOT::iterator got_it = m_GOT.getNextGOTPLTEntry();
- assert(got_it != m_GOT.getGOTPLTEnd() &&
- "The number of GOTPLT and PLT doesn't match");
-
- PLTEntry = llvm::cast<ARMPLT1>(&(*m_PLTEntryIterator));
- GOTPLTEntry = llvm::cast<GOTEntry>(&(*got_it));
- }
-
- return GOTPLTEntry;
+ return llvm::cast<ARMPLT1>(&(*m_PLTEntryIterator));
}
ARMPLT0* ARMPLT::getPLT0() const {
- iterator first = m_SectionData.getFragmentList().begin();
+ iterator first = m_SectionData->getFragmentList().begin();
- assert(first != m_SectionData.getFragmentList().end() &&
+ assert(first != m_SectionData->getFragmentList().end() &&
"FragmentList is empty, getPLT0 failed!");
ARMPLT0* plt0 = &(llvm::cast<ARMPLT0>(*first));
@@ -148,7 +116,7 @@
uint64_t plt_base = m_Section.addr();
assert(plt_base && ".plt base address is NULL!");
- uint64_t got_base = m_GOT.getSection().addr();
+ uint64_t got_base = m_GOT.addr();
assert(got_base && ".got base address is NULL!");
uint32_t offset = 0;
@@ -158,9 +126,9 @@
else
offset = (plt_base + 16) - got_base;
- iterator first = m_SectionData.getFragmentList().begin();
+ iterator first = m_SectionData->getFragmentList().begin();
- assert(first != m_SectionData.getFragmentList().end() &&
+ assert(first != m_SectionData->getFragmentList().end() &&
"FragmentList is empty, applyPLT0 failed!");
ARMPLT0* plt0 = &(llvm::cast<ARMPLT0>(*first));
@@ -182,11 +150,11 @@
uint64_t plt_base = m_Section.addr();
assert(plt_base && ".plt base address is NULL!");
- uint64_t got_base = m_GOT.getSection().addr();
+ uint64_t got_base = m_GOT.addr();
assert(got_base && ".got base address is NULL!");
- ARMPLT::iterator it = m_SectionData.begin();
- ARMPLT::iterator ie = m_SectionData.end();
+ ARMPLT::iterator it = m_SectionData->begin();
+ ARMPLT::iterator ie = m_SectionData->end();
assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
uint32_t GOTEntrySize = m_GOT.getEntrySize();
@@ -223,7 +191,7 @@
PLTEntryAddress += PLT1EntrySize;
}
- m_GOT.applyAllGOTPLT(plt_base);
+ m_GOT.applyGOTPLT(plt_base);
}
uint64_t ARMPLT::emit(MemoryRegion& pRegion)
diff --git a/lib/Target/ARM/ARMPLT.h b/lib/Target/ARM/ARMPLT.h
index db36563..67b6f4e 100644
--- a/lib/Target/ARM/ARMPLT.h
+++ b/lib/Target/ARM/ARMPLT.h
@@ -9,23 +9,22 @@
#ifndef MCLD_ARM_PLT_H
#define MCLD_ARM_PLT_H
-#include <mcld/LD/SectionData.h>
+#include <mcld/Target/GOT.h>
#include <mcld/Target/PLT.h>
namespace mcld {
class ARMGOT;
-class GOTEntry;
class MemoryRegion;
-class ARMPLT0 : public PLTEntry {
+class ARMPLT0 : public PLT::Entry {
public:
- ARMPLT0(SectionData* pParent);
+ ARMPLT0(SectionData& pParent);
};
-class ARMPLT1 : public PLTEntry {
+class ARMPLT1 : public PLT::Entry {
public:
- ARMPLT1(SectionData* pParent);
+ ARMPLT1(SectionData& pParent);
};
/** \class ARMPLT
@@ -33,34 +32,19 @@
*/
class ARMPLT : public PLT
{
- typedef llvm::DenseMap<const ResolveInfo*, ARMPLT1*> SymbolIndexType;
-
public:
- typedef SectionData::iterator iterator;
- typedef SectionData::const_iterator const_iterator;
-
-public:
- ARMPLT(LDSection& pSection, SectionData& pSectionData, ARMGOT& pGOTPLT);
+ ARMPLT(LDSection& pSection, ARMGOT& pGOTPLT);
~ARMPLT();
-// Override virtual function.
-public:
+ // finalizeSectionSize - set LDSection size
+ void finalizeSectionSize();
- // reserveEntry is ARMGOT friend function.
+ // hasPLT1 - return if this plt section has any plt1 entry
+ bool hasPLT1() const;
+
void reserveEntry(size_t pNum = 1) ;
- PLTEntry* getPLTEntry(const ResolveInfo& pSymbol, bool& pExist) ;
-
- GOTEntry* getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist);
-
-public:
- iterator begin() { return m_SectionData.begin(); }
-
- const_iterator begin() const { return m_SectionData.begin(); }
-
- iterator end() { return m_SectionData.end(); }
-
- const_iterator end() const { return m_SectionData.end(); }
+ ARMPLT1* consume();
ARMPLT0* getPLT0() const;
@@ -73,11 +57,8 @@
private:
ARMGOT& m_GOT;
- // Used by getEntry() for mapping a ResolveInfo
- // instance to a PLT1 Entry.
+ // Used by getEntry() for mapping a ResolveInfo instance to a PLT1 Entry.
iterator m_PLTEntryIterator;
-
- SymbolIndexType m_PLTEntryMap;
};
} // namespace of mcld
diff --git a/lib/Target/ARM/ARMRelocationFactory.cpp b/lib/Target/ARM/ARMRelocationFactory.cpp
index cc561db..d668fc5 100644
--- a/lib/Target/ARM/ARMRelocationFactory.cpp
+++ b/lib/Target/ARM/ARMRelocationFactory.cpp
@@ -11,10 +11,9 @@
#include <llvm/Support/DataTypes.h>
#include <llvm/Support/ELF.h>
#include <llvm/Support/Host.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/LD/Layout.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/Support/MsgHandling.h>
-
#include "ARMRelocationFactory.h"
#include "ARMRelocationFunctions.h"
@@ -28,7 +27,6 @@
/// the prototype of applying function
typedef RelocationFactory::Result (*ApplyFunctionType)(
Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent);
// the table entry of applying functions
@@ -58,17 +56,14 @@
}
RelocationFactory::Result
-ARMRelocationFactory::applyRelocation(Relocation& pRelocation,
- const MCLDInfo& pLDInfo)
+ARMRelocationFactory::applyRelocation(Relocation& pRelocation)
{
Relocation::Type type = pRelocation.type();
if (type > 130) { // 131-255 doesn't noted in ARM spec
- fatal(diag::unknown_relocation) << (int)type
- << pRelocation.symInfo()->name();
return RelocationFactory::Unknown;
}
- return ApplyFunctions[type].func(pRelocation, pLDInfo, *this);
+ return ApplyFunctions[type].func(pRelocation, *this);
}
const char* ARMRelocationFactory::getName(RelocationFactory::Type pType) const
@@ -117,117 +112,114 @@
// Check if symbol can use relocation R_ARM_RELATIVE
static bool
helper_use_relative_reloc(const ResolveInfo& pSym,
- const MCLDInfo& pLDInfo,
const ARMRelocationFactory& pFactory)
{
// if symbol is dynamic or undefine or preemptible
if (pSym.isDyn() ||
pSym.isUndef() ||
- pFactory.getTarget().isSymbolPreemptible(pSym,
- pLDInfo,
- pLDInfo.output()))
+ pFactory.getTarget().isSymbolPreemptible(pSym))
return false;
return true;
}
static
-GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
- ARMRelocationFactory& pParent)
+GOT::Entry& helper_get_GOT_and_init(Relocation& pReloc,
+ ARMRelocationFactory& pParent)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
ARMGNULDBackend& ld_backend = pParent.getTarget();
- bool exist;
- GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist);
- if (!exist) {
+ GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+ if (NULL == got_entry) {
+ got_entry = ld_backend.getGOT().consumeGOT();
+ pParent.getSymGOTMap().record(*rsym, *got_entry);
// If we first get this GOT entry, we should initialize it.
if (rsym->reserved() & ARMGNULDBackend::ReserveGOT) {
// No corresponding dynamic relocation, initialize to the symbol value.
- got_entry.setContent(pReloc.symValue());
+ got_entry->setContent(pReloc.symValue());
}
else if (rsym->reserved() & ARMGNULDBackend::GOTRel) {
// Initialize corresponding dynamic relocation.
- Relocation& rel_entry =
- *ld_backend.getRelDyn().getEntry(*rsym, true, exist);
- assert(!exist && "GOT entry not exist, but DynRel entry exist!");
+ Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
if ( rsym->isLocal() ||
- helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
+ helper_use_relative_reloc(*rsym, pParent)) {
// Initialize got entry to target symbol address
- got_entry.setContent(pReloc.symValue());
+ got_entry->setContent(pReloc.symValue());
rel_entry.setType(llvm::ELF::R_ARM_RELATIVE);
rel_entry.setSymInfo(0);
}
else {
// Initialize got entry to 0 for corresponding dynamic relocation.
- got_entry.setContent(0);
+ got_entry->setContent(0);
rel_entry.setType(llvm::ELF::R_ARM_GLOB_DAT);
rel_entry.setSymInfo(rsym);
}
- rel_entry.targetRef().assign(got_entry);
+ rel_entry.targetRef().assign(*got_entry);
}
else {
fatal(diag::reserve_entry_number_mismatch_got);
}
}
- return got_entry;
+ return *got_entry;
}
static
ARMRelocationFactory::Address helper_GOT_ORG(ARMRelocationFactory& pParent)
{
- return pParent.getTarget().getGOT().getSection().addr();
+ return pParent.getTarget().getGOT().addr();
}
static
ARMRelocationFactory::Address helper_GOT(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
- GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pLDInfo, pParent);
- return helper_GOT_ORG(pParent) + pParent.getLayout().getOutputOffset(got_entry);
+ GOT::Entry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
+ return helper_GOT_ORG(pParent) + got_entry.getOffset();
}
static
-PLTEntry& helper_get_PLT_and_init(Relocation& pReloc,
- ARMRelocationFactory& pParent)
+PLT::Entry& helper_get_PLT_and_init(Relocation& pReloc,
+ ARMRelocationFactory& pParent)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
ARMGNULDBackend& ld_backend = pParent.getTarget();
- bool exist;
- PLTEntry& plt_entry = *ld_backend.getPLT().getPLTEntry(*rsym, exist);
- if (!exist) {
- // If we first get this PLT entry, we should initialize it.
- if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
- GOTEntry& gotplt_entry =
- *ld_backend.getPLT().getGOTPLTEntry(*rsym, exist);
- // Initialize corresponding dynamic relocation.
- Relocation& rel_entry =
- *ld_backend.getRelPLT().getEntry(*rsym, true, exist);
- assert(!exist && "PLT entry not exist, but DynRel entry exist!");
- rel_entry.setType(llvm::ELF::R_ARM_JUMP_SLOT);
- rel_entry.targetRef().assign(gotplt_entry);
- rel_entry.setSymInfo(rsym);
- }
- else {
- fatal(diag::reserve_entry_number_mismatch_plt);
- }
+ PLT::Entry* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
+ if (NULL != plt_entry)
+ return *plt_entry;
+
+ plt_entry = ld_backend.getPLT().consume();
+ pParent.getSymPLTMap().record(*rsym, *plt_entry);
+
+ // If we first get this PLT entry, we should initialize it.
+ if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
+ GOT::Entry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
+ assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
+ gotplt_entry = ld_backend.getGOT().consumeGOTPLT();
+ pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
+
+ // Initialize corresponding dynamic relocation.
+ Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
+ rel_entry.setType(llvm::ELF::R_ARM_JUMP_SLOT);
+ rel_entry.targetRef().assign(*gotplt_entry);
+ rel_entry.setSymInfo(rsym);
}
- return plt_entry;
+ else {
+ fatal(diag::reserve_entry_number_mismatch_plt);
+ }
+
+ return *plt_entry;
}
-
-
static
ARMRelocationFactory::Address helper_PLT_ORG(ARMRelocationFactory& pParent)
{
- return pParent.getTarget().getPLT().getSection().addr();
+ return pParent.getTarget().getPLT().addr();
}
@@ -235,8 +227,8 @@
ARMRelocationFactory::Address helper_PLT(Relocation& pReloc,
ARMRelocationFactory& pParent)
{
- PLTEntry& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
- return helper_PLT_ORG(pParent) + pParent.getLayout().getOutputOffset(plt_entry);
+ PLT::Entry& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
+ return helper_PLT_ORG(pParent) + plt_entry.getOffset();
}
// Get an relocation entry in .rel.dyn and set its type to pType,
@@ -249,10 +241,8 @@
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
ARMGNULDBackend& ld_backend = pParent.getTarget();
- bool exist;
- Relocation& rel_entry =
- *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
+ Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
rel_entry.setType(pType);
rel_entry.targetRef() = pReloc.targetRef();
@@ -282,39 +272,27 @@
}
static ARMRelocationFactory::DWord
-helper_extract_thumb_movw_movt_addend(ARMRelocationFactory::DWord pTarget)
+helper_extract_thumb_movw_movt_addend(ARMRelocationFactory::DWord pValue)
{
- // Consider the endianness problem, get the target data value from lower
- // and upper 16 bits
- ARMRelocationFactory::DWord val =
- (*(reinterpret_cast<uint16_t*>(&pTarget)) << 16) |
- *(reinterpret_cast<uint16_t*>(&pTarget) + 1);
-
// imm16: [19-16][26][14-12][7-0]
- return helper_sign_extend((((val >> 4) & 0xf000U) |
- ((val >> 15) & 0x0800U) |
- ((val >> 4) & 0x0700U) |
- (val & 0x00ffU)),
+ return helper_sign_extend((((pValue >> 4) & 0xf000U) |
+ ((pValue >> 15) & 0x0800U) |
+ ((pValue >> 4) & 0x0700U) |
+ (pValue& 0x00ffU)),
16);
}
static ARMRelocationFactory::DWord
-helper_insert_val_thumb_movw_movt_inst(ARMRelocationFactory::DWord pTarget,
+helper_insert_val_thumb_movw_movt_inst(ARMRelocationFactory::DWord pValue,
ARMRelocationFactory::DWord pImm)
{
- ARMRelocationFactory::DWord val;
// imm16: [19-16][26][14-12][7-0]
- pTarget &= 0xfbf08f00U;
- pTarget |= (pImm & 0xf000U) << 4;
- pTarget |= (pImm & 0x0800U) << 15;
- pTarget |= (pImm & 0x0700U) << 4;
- pTarget |= (pImm & 0x00ffU);
-
- // Consider the endianness problem, write back data from lower and
- // upper 16 bits
- val = (*(reinterpret_cast<uint16_t*>(&pTarget)) << 16) |
- *(reinterpret_cast<uint16_t*>(&pTarget) + 1);
- return val;
+ pValue &= 0xfbf08f00U;
+ pValue |= (pImm & 0xf000U) << 4;
+ pValue |= (pImm & 0x0800U) << 15;
+ pValue |= (pImm & 0x0700U) << 4;
+ pValue |= (pImm & 0x00ffU);
+ return pValue;
}
static ARMRelocationFactory::DWord
@@ -377,7 +355,6 @@
// R_ARM_NONE
ARMRelocationFactory::Result none(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
return ARMRelocationFactory::OK;
@@ -385,7 +362,6 @@
// R_ARM_ABS32: (S + A) | T
ARMRelocationFactory::Result abs32(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
@@ -393,13 +369,11 @@
ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
ARMRelocationFactory::DWord S = pReloc.symValue();
- const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
- *(pReloc.targetRef().frag()));
- assert(NULL != target_sect);
+ LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
// If the flag of target section is not ALLOC, we will not scan this relocation
// but perform static relocation. (e.g., applying .debug section)
- if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+ if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
pReloc.target() = (S + A) | T;
return ARMRelocationFactory::OK;
}
@@ -416,13 +390,12 @@
if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
S = helper_PLT(pReloc, pParent);
T = 0 ; // PLT is not thumb
- pReloc.target() = (S + A) | T;
}
// If we generate a dynamic relocation (except R_ARM_RELATIVE)
// for a place, we should not perform static relocation on it
// in order to keep the addend store in the place correct.
if (rsym->reserved() & ARMGNULDBackend::ReserveRel) {
- if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
+ if (helper_use_relative_reloc(*rsym, pParent)) {
helper_DynRel(pReloc, llvm::ELF::R_ARM_RELATIVE, pParent);
}
else {
@@ -440,31 +413,39 @@
// R_ARM_REL32: ((S + A) | T) - P
ARMRelocationFactory::Result rel32(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
// perform static relocation
- ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- pReloc.target() = ((pReloc.symValue() + A) | T)
- - pReloc.place(pParent.getLayout());
+ ARMRelocationFactory::Address S = pReloc.symValue();
+ ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+ ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+
+ // An external symbol may need PLT (this reloc is from stub)
+ if (!pReloc.symInfo()->isLocal()) {
+ if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
+ S = helper_PLT(pReloc, pParent);
+ T = 0; // PLT is not thumb.
+ }
+ }
+
+ // perform relocation
+ pReloc.target() = ((S + A) | T) - pReloc.place();
+
return ARMRelocationFactory::OK;
}
// R_ARM_BASE_PREL: B(S) + A - P
ARMRelocationFactory::Result base_prel(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
// perform static relocation
ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- pReloc.target() = pReloc.symValue() + A - pReloc.place(pParent.getLayout());
+ pReloc.target() = pReloc.symValue() + A - pReloc.place();
return ARMRelocationFactory::OK;
}
// R_ARM_GOTOFF32: ((S + A) | T) - GOT_ORG
ARMRelocationFactory::Result gotoff32(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
ARMRelocationFactory::DWord T = getThumbBit(pReloc);
@@ -478,14 +459,13 @@
// R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG
ARMRelocationFactory::Result got_brel(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
if (!(pReloc.symInfo()->reserved() &
(ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) {
return ARMRelocationFactory::BadReloc;
}
- ARMRelocationFactory::Address GOT_S = helper_GOT(pReloc, pLDInfo, pParent);
+ ARMRelocationFactory::Address GOT_S = helper_GOT(pReloc, pParent);
ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
ARMRelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
// Apply relocation.
@@ -495,16 +475,16 @@
// R_ARM_GOT_PREL: GOT(S) + A - P
ARMRelocationFactory::Result got_prel(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
if (!(pReloc.symInfo()->reserved() &
(ARMGNULDBackend::ReserveGOT | ARMGNULDBackend::GOTRel))) {
return ARMRelocationFactory::BadReloc;
}
- ARMRelocationFactory::Address GOT_S = helper_GOT(pReloc, pLDInfo, pParent);
+ ARMRelocationFactory::Address GOT_S = helper_GOT(pReloc, pParent);
ARMRelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
+ ARMRelocationFactory::Address P = pReloc.place();
+
// Apply relocation.
pReloc.target() = GOT_S + A - P;
return ARMRelocationFactory::OK;
@@ -514,13 +494,8 @@
// R_ARM_JUMP24: ((S + A) | T) - P
// R_ARM_CALL: ((S + A) | T) - P
ARMRelocationFactory::Result call(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
- // TODO: Some issue have not been considered:
- // 1. Add stub when switching mode or jump target too far
- // 2. We assume the blx is available
-
// If target is undefined weak symbol, we only need to jump to the
// next instruction unless it has PLT entry. Rewrite instruction
// to NOP.
@@ -538,7 +513,7 @@
ARMRelocationFactory::DWord A =
helper_sign_extend((pReloc.target() & 0x00FFFFFFu) << 2, 26)
+ pReloc.addend();
- ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
+ ARMRelocationFactory::Address P = pReloc.place();
S = pReloc.symValue();
if (pReloc.symInfo()->reserved() & ARMGNULDBackend::ReservePLT) {
@@ -546,12 +521,15 @@
T = 0; // PLT is not thumb.
}
- // If the jump target is thumb instruction, switch mode is needed, rewrite
- // the instruction to BLX
+ // At this moment (after relaxation), if the jump target is thumb instruction,
+ // switch mode is needed, rewrite the instruction to BLX
+ // FIXME: check if we can use BLX instruction (check from .ARM.attribute
+ // CPU ARCH TAG, which should be ARMv5 or above)
if (T != 0) {
- // cannot rewrite R_ARM_JUMP24 instruction to blx
- assert((pReloc.type() != llvm::ELF::R_ARM_JUMP24)&&
- "Invalid instruction to rewrite to blx for switching mode.");
+ // cannot rewrite to blx for R_ARM_JUMP24
+ if (pReloc.type() == llvm::ELF::R_ARM_JUMP24)
+ return ARMRelocationFactory::BadReloc;
+
pReloc.target() = (pReloc.target() & 0xffffff) |
0xfa000000 |
(((S + A - P) & 2) << 23);
@@ -569,7 +547,6 @@
// R_ARM_THM_CALL: ((S + A) | T) - P
// R_ARM_THM_JUMP24: (((S + A) | T) - P)
ARMRelocationFactory::Result thm_call(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
// If target is undefined weak symbol, we only need to jump to the
@@ -584,13 +561,13 @@
}
// get lower and upper 16 bit instructions from relocation targetData
- uint16_t upper16 = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
- uint16_t lower16 = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
+ uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
+ uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord A = helper_thumb32_branch_offset(upper16,
- lower16);
- ARMRelocationFactory::Address P = pReloc.place(pParent.getLayout());
+ ARMRelocationFactory::DWord A = helper_thumb32_branch_offset(upper_inst,
+ lower_inst);
+ ARMRelocationFactory::Address P = pReloc.place();
ARMRelocationFactory::Address S;
// if symbol has plt
@@ -604,45 +581,44 @@
S = S + A;
+ // At this moment (after relaxation), if the jump target is arm
+ // instruction, switch mode is needed, rewrite the instruction to BLX
// FIXME: check if we can use BLX instruction (check from .ARM.attribute
// CPU ARCH TAG, which should be ARMv5 or above)
-
- // If the jump target is not thumb, switch mode is needed, rewrite
- // instruction to BLX
if (T == 0) {
+ // cannot rewrite to blx for R_ARM_THM_JUMP24
+ if (pReloc.type() == llvm::ELF::R_ARM_THM_JUMP24)
+ return ARMRelocationFactory::BadReloc;
+
// for BLX, select bit 1 from relocation base address to jump target
// address
S = helper_bit_select(S, P, 0x2);
// rewrite instruction to BLX
- lower16 &= ~0x1000U;
+ lower_inst &= ~0x1000U;
}
else {
// otherwise, the instruction should be BL
- lower16 |= 0x1000U;
+ lower_inst |= 0x1000U;
}
ARMRelocationFactory::DWord X = (S | T) - P;
- // TODO: check if we need stub when building non-shared object,
- // overflow or switch-mode.
-
// FIXME: Check bit size is 24(thumb2) or 22?
if (helper_check_signed_overflow(X, 25)) {
return ARMRelocationFactory::Overflow;
}
- upper16 = helper_thumb32_branch_upper(upper16, X);
- lower16 = helper_thumb32_branch_lower(lower16, X);
+ upper_inst = helper_thumb32_branch_upper(upper_inst, X);
+ lower_inst = helper_thumb32_branch_lower(lower_inst, X);
- *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper16;
- *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower16;
+ *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
+ *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
- return ARMRelocationFactory::OK;
+ return ARMRelocationFactory::OK;
}
// R_ARM_MOVW_ABS_NC: (S + A) | T
ARMRelocationFactory::Result movw_abs_nc(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
@@ -652,12 +628,11 @@
helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
ARMRelocationFactory::DWord X;
- const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
- *(pReloc.targetRef().frag()));
- assert(NULL != target_sect);
+ LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
+
// If the flag of target section is not ALLOC, we will not scan this
// relocation but perform static relocation. (e.g., applying .debug section)
- if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+ if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
// use plt
if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
S = helper_PLT(pReloc, pParent);
@@ -674,12 +649,11 @@
// R_ARM_MOVW_PREL_NC: ((S + A) | T) - P
ARMRelocationFactory::Result movw_prel_nc(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
ARMRelocationFactory::Address S = pReloc.symValue();
ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+ ARMRelocationFactory::DWord P = pReloc.place();
ARMRelocationFactory::DWord A =
helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
ARMRelocationFactory::DWord X;
@@ -696,7 +670,6 @@
// R_ARM_MOVT_ABS: S + A
ARMRelocationFactory::Result movt_abs(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
@@ -705,12 +678,11 @@
helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
ARMRelocationFactory::DWord X;
- const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
- *(pReloc.targetRef().frag()));
- assert(NULL != target_sect);
+ LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
+
// If the flag of target section is not ALLOC, we will not scan this relocation
// but perform static relocation. (e.g., applying .debug section)
- if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+ if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
// use plt
if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
S = helper_PLT(pReloc, pParent);
@@ -726,13 +698,12 @@
// R_ARM_MOVT_PREL: S + A - P
ARMRelocationFactory::Result movt_prel(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
ARMRelocationFactory::Address S = pReloc.symValue();
- ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+ ARMRelocationFactory::DWord P = pReloc.place();
ARMRelocationFactory::DWord A =
- helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
+ helper_extract_movw_movt_addend(pReloc.target()) + pReloc.addend();
ARMRelocationFactory::DWord X;
X = S + A - P;
@@ -744,22 +715,24 @@
// R_ARM_THM_MOVW_ABS_NC: (S + A) | T
ARMRelocationFactory::Result thm_movw_abs_nc(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
ARMRelocationFactory::Address S = pReloc.symValue();
ARMRelocationFactory::DWord T = getThumbBit(pReloc);
+
+ // get lower and upper 16 bit instructions from relocation targetData
+ uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
+ uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
+ ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
ARMRelocationFactory::DWord A =
- helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+ helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
ARMRelocationFactory::DWord X;
- const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
- *(pReloc.targetRef().frag()));
- assert(NULL != target_sect);
+ LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
// If the flag of target section is not ALLOC, we will not scan this relocation
// but perform static relocation. (e.g., applying .debug section)
- if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+ if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
// use plt
if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
S = helper_PLT(pReloc, pParent);
@@ -767,69 +740,84 @@
}
}
X = (S + A) | T;
- pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
- X);
+
+ val = helper_insert_val_thumb_movw_movt_inst(val, X);
+ *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
+ *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
+
return ARMRelocationFactory::OK;
}
// R_ARM_THM_MOVW_PREL_NC: ((S + A) | T) - P
ARMRelocationFactory::Result thm_movw_prel_nc(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
ARMRelocationFactory::Address S = pReloc.symValue();
ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+ ARMRelocationFactory::DWord P = pReloc.place();
+
+ // get lower and upper 16 bit instructions from relocation targetData
+ uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
+ uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
+ ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
ARMRelocationFactory::DWord A =
- helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+ helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
ARMRelocationFactory::DWord X;
X = ((S + A) | T) - P;
- // check 16-bit overflow
- pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
- X);
+ val = helper_insert_val_thumb_movw_movt_inst(val, X);
+ *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
+ *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
+
return ARMRelocationFactory::OK;
}
// R_ARM_THM_MOVW_BREL_NC: ((S + A) | T) - B(S)
// R_ARM_THM_MOVW_BREL: ((S + A) | T) - B(S)
ARMRelocationFactory::Result thm_movw_brel(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
ARMRelocationFactory::Address S = pReloc.symValue();
ARMRelocationFactory::DWord T = getThumbBit(pReloc);
- ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+ ARMRelocationFactory::DWord P = pReloc.place();
+
+ // get lower and upper 16 bit instructions from relocation targetData
+ uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
+ uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
+ ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
ARMRelocationFactory::DWord A =
- helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+ helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
ARMRelocationFactory::DWord X;
X = ((S + A) | T) - P;
- // check 16-bit overflow
- pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
- X);
+ val = helper_insert_val_thumb_movw_movt_inst(val, X);
+ *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
+ *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
+
return ARMRelocationFactory::OK;
}
// R_ARM_THM_MOVT_ABS: S + A
ARMRelocationFactory::Result thm_movt_abs(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
ARMRelocationFactory::Address S = pReloc.symValue();
+
+ // get lower and upper 16 bit instructions from relocation targetData
+ uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
+ uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
+ ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
ARMRelocationFactory::DWord A =
- helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+ helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
ARMRelocationFactory::DWord X;
- const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
- *(pReloc.targetRef().frag()));
- assert(NULL != target_sect);
+ LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
// If the flag of target section is not ALLOC, we will not scan this relocation
// but perform static relocation. (e.g., applying .debug section)
- if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+ if (0x0 != (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
// use plt
if (rsym->reserved() & ARMGNULDBackend::ReservePLT) {
S = helper_PLT(pReloc, pParent);
@@ -843,8 +831,9 @@
if (helper_check_signed_overflow(X, 16)) {
return ARMRelocationFactory::Overflow;
} else {
- pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
- X);
+ val = helper_insert_val_thumb_movw_movt_inst(val, X);
+ *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
+ *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
return ARMRelocationFactory::OK;
}
}
@@ -852,31 +841,38 @@
// R_ARM_THM_MOVT_PREL: S + A - P
// R_ARM_THM_MOVT_BREL: S + A - B(S)
ARMRelocationFactory::Result thm_movt_prel(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
ARMRelocationFactory::Address S = pReloc.symValue();
- ARMRelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+ ARMRelocationFactory::DWord P = pReloc.place();
+
+ // get lower and upper 16 bit instructions from relocation targetData
+ uint16_t upper_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()));
+ uint16_t lower_inst = *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1);
+ ARMRelocationFactory::DWord val = ((upper_inst) << 16) | (lower_inst);
ARMRelocationFactory::DWord A =
- helper_extract_thumb_movw_movt_addend(pReloc.target()) + pReloc.addend();
+ helper_extract_thumb_movw_movt_addend(val) + pReloc.addend();
ARMRelocationFactory::DWord X;
X = S + A - P;
X >>= 16;
- pReloc.target() = helper_insert_val_thumb_movw_movt_inst(pReloc.target(),
- X);
+
+ val = helper_insert_val_thumb_movw_movt_inst(val, X);
+ *(reinterpret_cast<uint16_t*>(&pReloc.target())) = upper_inst;
+ *(reinterpret_cast<uint16_t*>(&pReloc.target()) + 1) = lower_inst;
+
return ARMRelocationFactory::OK;
}
-// R_ARM_PREL31: (S + A) | T
+// R_ARM_PREL31: ((S + A) | T) - P
ARMRelocationFactory::Result prel31(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
ARMRelocationFactory::DWord target = pReloc.target();
ARMRelocationFactory::DWord T = getThumbBit(pReloc);
ARMRelocationFactory::DWord A = helper_sign_extend(target, 31) +
pReloc.addend();
+ ARMRelocationFactory::DWord P = pReloc.place();
ARMRelocationFactory::Address S;
S = pReloc.symValue();
@@ -886,7 +882,7 @@
T = 0; // PLT is not thumb.
}
- ARMRelocationFactory::DWord X = (S + A) | T ;
+ ARMRelocationFactory::DWord X = ((S + A) | T) - P;
pReloc.target() = helper_bit_select(target, X, 0x7fffffffU);
if (helper_check_signed_overflow(X, 31))
return ARMRelocationFactory::Overflow;
@@ -897,14 +893,12 @@
// R_ARM_TLS_IE32: GOT(S) + A - P
// R_ARM_TLS_LE32: S + A - tp
ARMRelocationFactory::Result tls(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
return ARMRelocationFactory::Unsupport;
}
ARMRelocationFactory::Result unsupport(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
ARMRelocationFactory& pParent)
{
return ARMRelocationFactory::Unsupport;
diff --git a/lib/Target/ARM/ARMRelocationFactory.h b/lib/Target/ARM/ARMRelocationFactory.h
index b0b3483..25135ed 100644
--- a/lib/Target/ARM/ARMRelocationFactory.h
+++ b/lib/Target/ARM/ARMRelocationFactory.h
@@ -14,10 +14,10 @@
#include <mcld/LD/RelocationFactory.h>
#include <mcld/Target/GOT.h>
+#include <mcld/Target/SymbolEntryMap.h>
#include "ARMLDBackend.h"
-namespace mcld
-{
+namespace mcld {
/** \class ARMRelocationFactory
* \brief ARMRelocationFactory creates and destroys the ARM relocations.
@@ -26,10 +26,14 @@
class ARMRelocationFactory : public RelocationFactory
{
public:
+ typedef SymbolEntryMap<GOT::Entry> SymGOTMap;
+ typedef SymbolEntryMap<PLT::Entry> SymPLTMap;
+
+public:
ARMRelocationFactory(size_t pNum, ARMGNULDBackend& pParent);
~ARMRelocationFactory();
- Result applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo);
+ Result applyRelocation(Relocation& pRelocation);
ARMGNULDBackend& getTarget()
{ return m_Target; }
@@ -39,8 +43,20 @@
const char* getName(Relocation::Type pType) const;
+ const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; }
+ SymGOTMap& getSymGOTMap() { return m_SymGOTMap; }
+
+ const SymPLTMap& getSymPLTMap() const { return m_SymPLTMap; }
+ SymPLTMap& getSymPLTMap() { return m_SymPLTMap; }
+
+ const SymGOTMap& getSymGOTPLTMap() const { return m_SymGOTPLTMap; }
+ SymGOTMap& getSymGOTPLTMap() { return m_SymGOTPLTMap; }
+
private:
ARMGNULDBackend& m_Target;
+ SymGOTMap m_SymGOTMap;
+ SymPLTMap m_SymPLTMap;
+ SymGOTMap m_SymGOTPLTMap;
};
} // namespace of mcld
diff --git a/lib/Target/ARM/ARMRelocationFunctions.h b/lib/Target/ARM/ARMRelocationFunctions.h
index bb6e727..3f8b90e 100644
--- a/lib/Target/ARM/ARMRelocationFunctions.h
+++ b/lib/Target/ARM/ARMRelocationFunctions.h
@@ -9,7 +9,6 @@
#define DECL_ARM_APPLY_RELOC_FUNC(Name) \
static ARMRelocationFactory::Result Name (Relocation& pEntry, \
- const MCLDInfo& pLDInfo, \
ARMRelocationFactory& pParent);
#define DECL_ARM_APPLY_RELOC_FUNCS \
diff --git a/lib/Target/ARM/ARMSectLinker.cpp b/lib/Target/ARM/ARMSectLinker.cpp
deleted file mode 100644
index 52a00e3..0000000
--- a/lib/Target/ARM/ARMSectLinker.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//===- ARMSectLinker.cpp --------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <llvm/ADT/Triple.h>
-#include <mcld/Support/TargetRegistry.h>
-#include "ARM.h"
-#include "ARMELFSectLinker.h"
-
-
-using namespace mcld;
-
-namespace mcld {
-//===----------------------------------------------------------------------===//
-// createARMSectLinker - the help function to create corresponding ARMSectLinker
-//
-SectLinker* createARMSectLinker(const std::string &pTriple,
- SectLinkerOption &pOption,
- mcld::TargetLDBackend &pLDBackend)
-{
- Triple theTriple(pTriple);
- if (theTriple.isOSDarwin()) {
- assert(0 && "MachO linker has not supported yet");
- return NULL;
- }
- if (theTriple.isOSWindows()) {
- assert(0 && "COFF linker has not supported yet");
- return NULL;
- }
-
- // For now, use Android SectLinker directly
- return new ARMELFSectLinker(pOption, pLDBackend);
-}
-
-} // namespace of mcld
-
-//==========================
-// ARMSectLinker
-extern "C" void LLVMInitializeARMSectLinker() {
- // Register the linker frontend
- mcld::TargetRegistry::RegisterSectLinker(TheARMTarget, createARMSectLinker);
- mcld::TargetRegistry::RegisterSectLinker(TheThumbTarget, createARMSectLinker);
-}
-
diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp
index 54e1b3d..7062f31 100644
--- a/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/lib/Target/ARM/ARMTargetMachine.cpp
@@ -7,28 +7,26 @@
//
//===----------------------------------------------------------------------===//
#include "ARMTargetMachine.h"
-
-#include "mcld/Support/TargetRegistry.h"
-#include "mcld/MC/MCLDInfo.h"
#include "ARM.h"
-extern "C" void LLVMInitializeARMLDTarget() {
- // Register createTargetMachine function pointer to mcld::Target
- mcld::RegisterTargetMachine<mcld::ARMBaseTargetMachine> X(mcld::TheARMTarget);
- mcld::RegisterTargetMachine<mcld::ARMBaseTargetMachine> Y(mcld::TheThumbTarget);
-}
+#include <mcld/Support/TargetRegistry.h>
mcld::ARMBaseTargetMachine::ARMBaseTargetMachine(llvm::TargetMachine& pPM,
const mcld::Target &pTarget,
const std::string& pTriple)
- : mcld::LLVMTargetMachine(pPM, pTarget, pTriple) {
- // arg1 - the number of total attributes
- // arg2 - the most possible number of input files
- m_pLDInfo = new MCLDInfo(pTriple, 32, 64);
+ : mcld::MCLDTargetMachine(pPM, pTarget, pTriple) {
}
mcld::ARMBaseTargetMachine::~ARMBaseTargetMachine()
{
- delete m_pLDInfo;
+}
+
+//===----------------------------------------------------------------------===//
+// Initialize MCLDTargetMachine
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeARMLDTarget() {
+ // Register createTargetMachine function pointer to mcld::Target
+ mcld::RegisterTargetMachine<mcld::ARMBaseTargetMachine> X(mcld::TheARMTarget);
+ mcld::RegisterTargetMachine<mcld::ARMBaseTargetMachine> Y(mcld::TheThumbTarget);
}
diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h
index 19f8aa2..94a7866 100644
--- a/lib/Target/ARM/ARMTargetMachine.h
+++ b/lib/Target/ARM/ARMTargetMachine.h
@@ -8,30 +8,20 @@
//===----------------------------------------------------------------------===//
#ifndef MCLD_ARM_TARGET_MACHINE_H
#define MCLD_ARM_TARGET_MACHINE_H
-#include "mcld/Target/TargetMachine.h"
+
#include "ARM.h"
+#include <mcld/Target/TargetMachine.h>
-namespace mcld
+namespace mcld {
+
+class ARMBaseTargetMachine : public MCLDTargetMachine
{
-
-class ARMBaseTargetMachine : public LLVMTargetMachine
-{
-protected:
- MCLDInfo *m_pLDInfo;
-
public:
ARMBaseTargetMachine(llvm::TargetMachine &pTM,
const mcld::Target &pTarget,
const std::string &pTriple);
virtual ~ARMBaseTargetMachine();
-
- mcld::MCLDInfo& getLDInfo()
- { return *m_pLDInfo; }
-
- const mcld::MCLDInfo& getLDInfo() const
- { return *m_pLDInfo; }
-
};
} // namespace of mcld
diff --git a/lib/Target/ARM/ARMToARMStub.cpp b/lib/Target/ARM/ARMToARMStub.cpp
new file mode 100644
index 0000000..9bc26cd
--- /dev/null
+++ b/lib/Target/ARM/ARMToARMStub.cpp
@@ -0,0 +1,115 @@
+//===- ARMToARMStub.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARMToARMStub.h"
+#include "ARMLDBackend.h"
+
+#include <llvm/Support/ELF.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Relocation.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ARMToARMStub
+//===----------------------------------------------------------------------===//
+const uint32_t ARMToARMStub::PIC_TEMPLATE[] = {
+ 0xe59fc000, // ldr r12, [pc]
+ 0xe08ff00c, // add pc, pc, ip
+ 0x0 // dcd R_ARM_REL32(X-4)
+};
+
+const uint32_t ARMToARMStub::TEMPLATE[] = {
+ 0xe51ff004, // ldr pc, [pc, #-4]
+ 0x0 // dcd R_ARM_ABS32(X)
+};
+
+ARMToARMStub::ARMToARMStub(bool pIsOutputPIC)
+ : Stub(), m_Name("A2A_prototype"), m_pData(NULL), m_Size(0x0)
+{
+ if (pIsOutputPIC) {
+ m_pData = PIC_TEMPLATE;
+ m_Size = sizeof(PIC_TEMPLATE);
+ addFixup(8u, -4, llvm::ELF::R_ARM_REL32);
+ }
+ else {
+ m_pData = TEMPLATE;
+ m_Size = sizeof(TEMPLATE);
+ addFixup(4u, 0x0, llvm::ELF::R_ARM_ABS32);
+ }
+}
+
+/// for doClone
+ARMToARMStub::ARMToARMStub(const uint32_t* pData,
+ size_t pSize,
+ const_fixup_iterator pBegin,
+ const_fixup_iterator pEnd)
+ : Stub(), m_Name("A2A_veneer"), m_pData(pData), m_Size(pSize)
+{
+ for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
+ addFixup(**it);
+}
+
+ARMToARMStub::~ARMToARMStub()
+{
+}
+
+bool ARMToARMStub::isMyDuty(const class Relocation& pReloc,
+ uint64_t pSource,
+ uint64_t pTargetSymValue) const
+{
+ bool result = false;
+ // Check if the branch target is ARM
+ if ((pTargetSymValue & 0x1) == 0x0) {
+ switch (pReloc.type()) {
+ case llvm::ELF::R_ARM_CALL:
+ case llvm::ELF::R_ARM_JUMP24:
+ case llvm::ELF::R_ARM_PLT32: {
+ // Check if the branch target is too far
+ uint64_t dest = pTargetSymValue + pReloc.addend() + 8u;
+ int64_t branch_offset = static_cast<int64_t>(dest) - pSource;
+ if ((branch_offset > ARMGNULDBackend::ARM_MAX_FWD_BRANCH_OFFSET) ||
+ (branch_offset < ARMGNULDBackend::ARM_MAX_BWD_BRANCH_OFFSET)) {
+ result = true;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return result;
+}
+
+const std::string& ARMToARMStub::name() const
+{
+ return m_Name;
+}
+
+const uint8_t* ARMToARMStub::getContent() const
+{
+ return reinterpret_cast<const uint8_t*>(m_pData);
+}
+
+size_t ARMToARMStub::size() const
+{
+ return m_Size;
+}
+
+size_t ARMToARMStub::alignment() const
+{
+ return 4u;
+}
+
+Stub* ARMToARMStub::doClone()
+{
+ return new ARMToARMStub(m_pData, m_Size, fixup_begin(), fixup_end());
+}
+
diff --git a/lib/Target/ARM/ARMToARMStub.h b/lib/Target/ARM/ARMToARMStub.h
new file mode 100644
index 0000000..107f172
--- /dev/null
+++ b/lib/Target/ARM/ARMToARMStub.h
@@ -0,0 +1,76 @@
+//===- ARMToARMStub.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MCLD_ARM_ARMTOARMSTUB_H
+#define MCLD_ARM_ARMTOARMSTUB_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/Fragment/Stub.h>
+#include <string>
+#include <vector>
+
+namespace mcld
+{
+
+class Relocation;
+class ResolveInfo;
+
+/** \class ARMToARMStub
+ * \brief ARM stub for long call from ARM source to ARM target
+ *
+ */
+class ARMToARMStub : public Stub
+{
+public:
+ ARMToARMStub(bool pIsOutputPIC);
+
+ ~ARMToARMStub();
+
+ // isMyDuty
+ bool isMyDuty(const class Relocation& pReloc,
+ uint64_t pSource,
+ uint64_t pTargetSymValue) const;
+
+ // observers
+ const std::string& name() const;
+
+ const uint8_t* getContent() const;
+
+ size_t size() const;
+
+ size_t alignment() const;
+
+private:
+ ARMToARMStub(const ARMToARMStub&);
+
+ ARMToARMStub& operator=(const ARMToARMStub&);
+
+ /// for doClone
+ ARMToARMStub(const uint32_t* pData,
+ size_t pSize,
+ const_fixup_iterator pBegin,
+ const_fixup_iterator pEnd);
+
+ /// doClone
+ Stub* doClone();
+
+private:
+ std::string m_Name;
+ static const uint32_t PIC_TEMPLATE[];
+ static const uint32_t TEMPLATE[];
+ const uint32_t* m_pData;
+ size_t m_Size;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/ARM/ARMToTHMStub.cpp b/lib/Target/ARM/ARMToTHMStub.cpp
new file mode 100644
index 0000000..8c25c86
--- /dev/null
+++ b/lib/Target/ARM/ARMToTHMStub.cpp
@@ -0,0 +1,123 @@
+//===- ARMToTHMStub.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARMToTHMStub.h"
+#include "ARMLDBackend.h"
+
+#include <llvm/Support/ELF.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Relocation.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// ARMToTHMStub
+//===----------------------------------------------------------------------===//
+const uint32_t ARMToTHMStub::PIC_TEMPLATE[] = {
+ 0xe59fc004, // ldr r12, [pc, #4]
+ 0xe08fc00c, // add ip, pc, ip
+ 0xe12fff1c, // bx ip
+ 0x0 // dcd R_ARM_REL32(X)
+};
+
+const uint32_t ARMToTHMStub::TEMPLATE[] = {
+ 0xe59fc000, // ldr ip, [pc, #0]
+ 0xe12fff1c, // bx ip
+ 0x0 // dcd R_ARM_ABS32(X)
+};
+
+ARMToTHMStub::ARMToTHMStub(bool pIsOutputPIC)
+ : Stub(), m_Name("A2T_prototype"), m_pData(NULL), m_Size(0x0)
+{
+ if (pIsOutputPIC) {
+ m_pData = PIC_TEMPLATE;
+ m_Size = sizeof(PIC_TEMPLATE);
+ addFixup(12u, 0x0, llvm::ELF::R_ARM_REL32);
+ }
+ else {
+ m_pData = TEMPLATE;
+ m_Size = sizeof(TEMPLATE);
+ addFixup(8u, 0x0, llvm::ELF::R_ARM_ABS32);
+ }
+}
+
+/// for doClone
+ARMToTHMStub::ARMToTHMStub(const uint32_t* pData,
+ size_t pSize,
+ const_fixup_iterator pBegin,
+ const_fixup_iterator pEnd)
+ : Stub(), m_Name("A2T_veneer"), m_pData(pData), m_Size(pSize)
+{
+ for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
+ addFixup(**it);
+}
+
+ARMToTHMStub::~ARMToTHMStub()
+{
+}
+
+bool ARMToTHMStub::isMyDuty(const class Relocation& pReloc,
+ uint64_t pSource,
+ uint64_t pTargetSymValue) const
+{
+ bool result = false;
+ // Check if the branch target is THUMB
+ if ((pTargetSymValue & 0x1) != 0x0) {
+ switch (pReloc.type()) {
+ case llvm::ELF::R_ARM_CALL: {
+ // FIXME: Assuming blx is available (i.e., target is armv5 or above!)
+ // then, we do not need a stub unless the branch target is too far.
+ uint64_t dest = pTargetSymValue + pReloc.addend() + 8u;
+ int64_t branch_offset = static_cast<int64_t>(dest) - pSource;
+ if ((branch_offset > ARMGNULDBackend::ARM_MAX_FWD_BRANCH_OFFSET) ||
+ (branch_offset < ARMGNULDBackend::ARM_MAX_BWD_BRANCH_OFFSET)) {
+ result = true;
+ break;
+ }
+ break;
+ }
+ case llvm::ELF::R_ARM_JUMP24:
+ case llvm::ELF::R_ARM_PLT32: {
+ // always need a stub to switch mode
+ result = true;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return result;
+}
+
+const std::string& ARMToTHMStub::name() const
+{
+ return m_Name;
+}
+
+const uint8_t* ARMToTHMStub::getContent() const
+{
+ return reinterpret_cast<const uint8_t*>(m_pData);
+}
+
+size_t ARMToTHMStub::size() const
+{
+ return m_Size;
+}
+
+size_t ARMToTHMStub::alignment() const
+{
+ return 4u;
+}
+
+Stub* ARMToTHMStub::doClone()
+{
+ return new ARMToTHMStub(m_pData, m_Size, fixup_begin(), fixup_end());
+}
+
diff --git a/lib/Target/ARM/ARMToTHMStub.h b/lib/Target/ARM/ARMToTHMStub.h
new file mode 100644
index 0000000..b38303e
--- /dev/null
+++ b/lib/Target/ARM/ARMToTHMStub.h
@@ -0,0 +1,76 @@
+//===- ARMToTHMStub.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MCLD_ARM_ARMToTHMStub_H
+#define MCLD_ARM_ARMToTHMStub_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/Fragment/Stub.h>
+#include <string>
+#include <vector>
+
+namespace mcld
+{
+
+class Relocation;
+class ResolveInfo;
+
+/** \class ARMToTHMStub
+ * \brief ARM stub for long call from ARM source to ARM target
+ *
+ */
+class ARMToTHMStub : public Stub
+{
+public:
+ ARMToTHMStub(bool pIsOutputPIC);
+
+ ~ARMToTHMStub();
+
+ // isMyDuty
+ bool isMyDuty(const class Relocation& pReloc,
+ uint64_t pSource,
+ uint64_t pTargetSymValue) const;
+
+ // observers
+ const std::string& name() const;
+
+ const uint8_t* getContent() const;
+
+ size_t size() const;
+
+ size_t alignment() const;
+
+private:
+ ARMToTHMStub(const ARMToTHMStub&);
+
+ ARMToTHMStub& operator=(const ARMToTHMStub&);
+
+ /// for doClone
+ ARMToTHMStub(const uint32_t* pData,
+ size_t pSize,
+ const_fixup_iterator pBegin,
+ const_fixup_iterator pEnd);
+
+ /// doClone
+ Stub* doClone();
+
+private:
+ std::string m_Name;
+ static const uint32_t PIC_TEMPLATE[];
+ static const uint32_t TEMPLATE[];
+ const uint32_t* m_pData;
+ size_t m_Size;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/ARM/Android.mk b/lib/Target/ARM/Android.mk
index 114f2dc..f9cb356 100644
--- a/lib/Target/ARM/Android.mk
+++ b/lib/Target/ARM/Android.mk
@@ -3,13 +3,18 @@
mcld_arm_target_SRC_FILES := \
ARMDiagnostic.cpp \
ARMELFDynamic.cpp \
- ARMELFSectLinker.cpp \
+ ARMELFMCLinker.cpp \
+ ARMEmulation.cpp \
ARMGOT.cpp \
ARMLDBackend.cpp \
+ ARMMCLinker.cpp \
ARMPLT.cpp \
ARMRelocationFactory.cpp \
- ARMSectLinker.cpp \
- ARMTargetMachine.cpp
+ ARMTargetMachine.cpp \
+ ARMToARMStub.cpp \
+ ARMToTHMStub.cpp \
+ THMToARMStub.cpp \
+ THMToTHMStub.cpp
# For the host
# =====================================================
diff --git a/lib/Target/ARM/THMToARMStub.cpp b/lib/Target/ARM/THMToARMStub.cpp
new file mode 100644
index 0000000..e32222e
--- /dev/null
+++ b/lib/Target/ARM/THMToARMStub.cpp
@@ -0,0 +1,126 @@
+//===- THMToARMStub.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "THMToARMStub.h"
+#include "ARMLDBackend.h"
+
+#include <llvm/Support/ELF.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Relocation.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// THMToARMStub
+//===----------------------------------------------------------------------===//
+const uint32_t THMToARMStub::PIC_TEMPLATE[] = {
+ 0x46c04778, // bx pc ... nop
+ 0xe59fc000, // ldr ip, [pc, #0]
+ 0xe08cf00f, // add pc, ip, pc
+ 0x0 // dcd R_ARM_REL32(X)
+};
+
+const uint32_t THMToARMStub::TEMPLATE[] = {
+ 0x46c04778, // bx pc ... nop
+ 0xe51ff004, // ldr pc, [pc, #-4]
+ 0x0 // dcd R_ARM_ABS32(X)
+};
+
+THMToARMStub::THMToARMStub(bool pIsOutputPIC)
+ : Stub(), m_Name("T2A_prototype"), m_pData(NULL), m_Size(0x0)
+{
+ if (pIsOutputPIC) {
+ m_pData = PIC_TEMPLATE;
+ m_Size = sizeof(PIC_TEMPLATE);
+ addFixup(12u, -4, llvm::ELF::R_ARM_REL32);
+ }
+ else {
+ m_pData = TEMPLATE;
+ m_Size = sizeof(TEMPLATE);
+ addFixup(8u, 0x0, llvm::ELF::R_ARM_ABS32);
+ }
+}
+
+/// for doClone
+THMToARMStub::THMToARMStub(const uint32_t* pData,
+ size_t pSize,
+ const_fixup_iterator pBegin,
+ const_fixup_iterator pEnd)
+ : Stub(), m_Name("T2A_veneer"), m_pData(pData), m_Size(pSize)
+{
+ for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
+ addFixup(**it);
+}
+
+THMToARMStub::~THMToARMStub()
+{
+}
+
+bool THMToARMStub::isMyDuty(const class Relocation& pReloc,
+ uint64_t pSource,
+ uint64_t pTargetSymValue) const
+{
+ bool result = false;
+ // Check if the branch target is ARM
+ if ((pTargetSymValue & 0x1) == 0x0) {
+ switch (pReloc.type()) {
+ case llvm::ELF::R_ARM_THM_CALL: {
+ // FIXME: Assuming blx is available (i.e., target is armv5 or above!)
+ // then, we do not need a stub unless the branch target is too far.
+ uint64_t dest = pTargetSymValue + pReloc.addend() + 4u;
+ int64_t branch_offset = static_cast<int64_t>(dest) - pSource;
+ if ((branch_offset > ARMGNULDBackend::THM_MAX_FWD_BRANCH_OFFSET) ||
+ (branch_offset < ARMGNULDBackend::THM_MAX_BWD_BRANCH_OFFSET))
+ result = true;
+ break;
+ }
+ case llvm::ELF::R_ARM_THM_JUMP24: {
+ // always need a stub to switch mode
+ result = true;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return result;
+}
+
+const std::string& THMToARMStub::name() const
+{
+ return m_Name;
+}
+
+const uint8_t* THMToARMStub::getContent() const
+{
+ return reinterpret_cast<const uint8_t*>(m_pData);
+}
+
+size_t THMToARMStub::size() const
+{
+ return m_Size;
+}
+
+size_t THMToARMStub::alignment() const
+{
+ return 4u;
+}
+
+// for T bit of this stub
+uint64_t THMToARMStub::initSymValue() const
+{
+ return 0x1;
+}
+
+Stub* THMToARMStub::doClone()
+{
+ return new THMToARMStub(m_pData, m_Size, fixup_begin(), fixup_end());
+}
+
diff --git a/lib/Target/ARM/THMToARMStub.h b/lib/Target/ARM/THMToARMStub.h
new file mode 100644
index 0000000..994cc23
--- /dev/null
+++ b/lib/Target/ARM/THMToARMStub.h
@@ -0,0 +1,79 @@
+//===- THMToARMStub.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MCLD_ARM_THMToARMStub_H
+#define MCLD_ARM_THMToARMStub_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/Fragment/Stub.h>
+#include <string>
+#include <vector>
+
+namespace mcld
+{
+
+class Relocation;
+class ResolveInfo;
+
+/** \class THMToARMStub
+ * \brief ARM stub for long call from ARM source to ARM target
+ *
+ */
+class THMToARMStub : public Stub
+{
+public:
+ THMToARMStub(bool pIsOutputPIC);
+
+ ~THMToARMStub();
+
+ // isMyDuty
+ bool isMyDuty(const class Relocation& pReloc,
+ uint64_t pSource,
+ uint64_t pTargetSymValue) const;
+
+ // observers
+ const std::string& name() const;
+
+ const uint8_t* getContent() const;
+
+ size_t size() const;
+
+ size_t alignment() const;
+
+ // for T bit of this stub
+ uint64_t initSymValue() const;
+
+private:
+ THMToARMStub(const THMToARMStub&);
+
+ THMToARMStub& operator=(const THMToARMStub&);
+
+ /// for doClone
+ THMToARMStub(const uint32_t* pData,
+ size_t pSize,
+ const_fixup_iterator pBegin,
+ const_fixup_iterator pEnd);
+
+ /// doClone
+ Stub* doClone();
+
+private:
+ std::string m_Name;
+ static const uint32_t PIC_TEMPLATE[];
+ static const uint32_t TEMPLATE[];
+ const uint32_t* m_pData;
+ size_t m_Size;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/ARM/THMToTHMStub.cpp b/lib/Target/ARM/THMToTHMStub.cpp
new file mode 100644
index 0000000..b58de77
--- /dev/null
+++ b/lib/Target/ARM/THMToTHMStub.cpp
@@ -0,0 +1,122 @@
+//===- THMToTHMStub.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "THMToTHMStub.h"
+#include "ARMLDBackend.h"
+
+#include <llvm/Support/ELF.h>
+#include <mcld/LD/ResolveInfo.h>
+#include <mcld/LD/LDSymbol.h>
+#include <mcld/Fragment/Relocation.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// THMToTHMStub
+//===----------------------------------------------------------------------===//
+const uint32_t THMToTHMStub::PIC_TEMPLATE[] = {
+ 0x46c04778, // bx pc ... nop
+ 0xe59fc004, // ldr r12, [pc, #4]
+ 0xe08fc00c, // add ip, pc, ip
+ 0xe12fff1c, // bx ip
+ 0x0 // dcd R_ARM_REL32(X)
+};
+
+const uint32_t THMToTHMStub::TEMPLATE[] = {
+ 0x46c04778, // bx pc ... nop
+ 0xe59fc000, // ldr ip, [pc, #0]
+ 0xe12fff1c, // bx ip
+ 0x0 // dcd R_ARM_ABS32(X)
+};
+
+THMToTHMStub::THMToTHMStub(bool pIsOutputPIC)
+ : Stub(), m_Name("T2T_prototype"), m_pData(NULL), m_Size(0x0)
+{
+ if (pIsOutputPIC) {
+ m_pData = PIC_TEMPLATE;
+ m_Size = sizeof(PIC_TEMPLATE);
+ addFixup(16u, 0x0, llvm::ELF::R_ARM_REL32);
+ }
+ else {
+ m_pData = TEMPLATE;
+ m_Size = sizeof(TEMPLATE);
+ addFixup(12u, 0x0, llvm::ELF::R_ARM_ABS32);
+ }
+}
+
+/// for doClone
+THMToTHMStub::THMToTHMStub(const uint32_t* pData,
+ size_t pSize,
+ const_fixup_iterator pBegin,
+ const_fixup_iterator pEnd)
+ : Stub(), m_Name("T2T_veneer"), m_pData(pData), m_Size(pSize)
+{
+ for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
+ addFixup(**it);
+}
+
+THMToTHMStub::~THMToTHMStub()
+{
+}
+
+bool THMToTHMStub::isMyDuty(const class Relocation& pReloc,
+ uint64_t pSource,
+ uint64_t pTargetSymValue) const
+{
+ bool result = false;
+ // Check if the branch target is THUMB
+ if ((pTargetSymValue & 0x1) != 0x0) {
+ switch (pReloc.type()) {
+ case llvm::ELF::R_ARM_THM_CALL:
+ case llvm::ELF::R_ARM_THM_JUMP24: {
+ // Check if the branch target is too far
+ uint64_t dest = pTargetSymValue + pReloc.addend() + 4u;
+ int64_t branch_offset = static_cast<int64_t>(dest) - pSource;
+ if ((branch_offset > ARMGNULDBackend::THM_MAX_FWD_BRANCH_OFFSET) ||
+ (branch_offset < ARMGNULDBackend::THM_MAX_BWD_BRANCH_OFFSET))
+ result = true;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return result;
+}
+
+const std::string& THMToTHMStub::name() const
+{
+ return m_Name;
+}
+
+const uint8_t* THMToTHMStub::getContent() const
+{
+ return reinterpret_cast<const uint8_t*>(m_pData);
+}
+
+size_t THMToTHMStub::size() const
+{
+ return m_Size;
+}
+
+size_t THMToTHMStub::alignment() const
+{
+ return 4u;
+}
+
+uint64_t THMToTHMStub::initSymValue() const
+{
+ return 0x1;
+}
+
+Stub* THMToTHMStub::doClone()
+{
+ return new THMToTHMStub(m_pData, m_Size, fixup_begin(), fixup_end());
+}
+
diff --git a/lib/Target/ARM/THMToTHMStub.h b/lib/Target/ARM/THMToTHMStub.h
new file mode 100644
index 0000000..f8d6009
--- /dev/null
+++ b/lib/Target/ARM/THMToTHMStub.h
@@ -0,0 +1,79 @@
+//===- THMToTHMStub.h -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MCLD_ARM_THMToTHMStub_H
+#define MCLD_ARM_THMToTHMStub_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+
+#include <llvm/Support/DataTypes.h>
+#include <mcld/Fragment/Stub.h>
+#include <string>
+#include <vector>
+
+namespace mcld
+{
+
+class Relocation;
+class ResolveInfo;
+
+/** \class THMToTHMStub
+ * \brief ARM stub for long call from ARM source to ARM target
+ *
+ */
+class THMToTHMStub : public Stub
+{
+public:
+ THMToTHMStub(bool pIsOutputPIC);
+
+ ~THMToTHMStub();
+
+ // isMyDuty
+ bool isMyDuty(const class Relocation& pReloc,
+ uint64_t pSource,
+ uint64_t pTargetSymValue) const;
+
+ // observers
+ const std::string& name() const;
+
+ const uint8_t* getContent() const;
+
+ size_t size() const;
+
+ size_t alignment() const;
+
+ // for T bit of this stub
+ uint64_t initSymValue() const;
+
+private:
+ THMToTHMStub(const THMToTHMStub&);
+
+ THMToTHMStub& operator=(const THMToTHMStub&);
+
+ /// for doClone
+ THMToTHMStub(const uint32_t* pData,
+ size_t pSize,
+ const_fixup_iterator pBegin,
+ const_fixup_iterator pEnd);
+
+ /// doClone
+ Stub* doClone();
+
+private:
+ std::string m_Name;
+ static const uint32_t PIC_TEMPLATE[];
+ static const uint32_t TEMPLATE[];
+ const uint32_t* m_pData;
+ size_t m_Size;
+};
+
+} // namespace of mcld
+
+#endif
diff --git a/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
index 4f2f815..fd00641 100644
--- a/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
+++ b/lib/Target/ARM/TargetInfo/ARMTargetInfo.cpp
@@ -14,7 +14,7 @@
mcld::Target TheARMTarget;
mcld::Target TheThumbTarget;
-extern "C" void LLVMInitializeARMLDTargetInfo() {
+extern "C" void MCLDInitializeARMLDTargetInfo() {
// register into mcld::TargetRegistry
mcld::RegisterTarget X(TheARMTarget, "arm" );
mcld::RegisterTarget Y(TheThumbTarget, "thumb" );
diff --git a/lib/Target/Android.mk b/lib/Target/Android.mk
index abcc876..e70b467 100644
--- a/lib/Target/Android.mk
+++ b/lib/Target/Android.mk
@@ -2,12 +2,12 @@
mcld_target_SRC_FILES := \
ELFDynamic.cpp \
- ELFSectLinker.cpp \
+ ELFEmulation.cpp \
+ ELFMCLinker.cpp \
GNULDBackend.cpp \
GOT.cpp \
OutputRelocSection.cpp \
PLT.cpp \
- Stub.cpp \
Target.cpp \
TargetLDBackend.cpp
diff --git a/lib/Target/ELFDynamic.cpp b/lib/Target/ELFDynamic.cpp
index cb7c435..25b21f0 100644
--- a/lib/Target/ELFDynamic.cpp
+++ b/lib/Target/ELFDynamic.cpp
@@ -11,8 +11,9 @@
#include <mcld/Target/ELFDynamic.h>
#include <mcld/Target/GNULDBackend.h>
#include <mcld/LD/ELFFileFormat.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MsgHandling.h>
using namespace mcld;
using namespace elf_dynamic;
@@ -30,7 +31,7 @@
//===----------------------------------------------------------------------===//
// ELFDynamic
ELFDynamic::ELFDynamic(const GNULDBackend& pParent)
- : m_pEntryFactory(NULL), m_Idx(0) {
+ : m_pEntryFactory(NULL), m_Backend(pParent), m_Idx(0) {
if (32 == pParent.bitclass() && pParent.isLittleEndian()) {
m_pEntryFactory = new Entry<32, true>();
}
@@ -85,13 +86,13 @@
}
/// reserveEntries - reserve entries
-void ELFDynamic::reserveEntries(const MCLDInfo& pLDInfo,
+void ELFDynamic::reserveEntries(const LinkerConfig& pConfig,
const ELFFileFormat& pFormat)
{
- if (pLDInfo.output().type() == Output::DynObj) {
+ if (LinkerConfig::DynObj == pConfig.codeGenType()) {
reserveOne(llvm::ELF::DT_SONAME); // DT_SONAME
- if (pLDInfo.options().Bsymbolic())
+ if (pConfig.options().Bsymbolic())
reserveOne(llvm::ELF::DT_SYMBOLIC); // DT_SYMBOLIC
}
@@ -146,24 +147,29 @@
reserveOne(llvm::ELF::DT_RELAENT); // DT_RELAENT
}
- if (pLDInfo.options().hasOrigin() ||
- pLDInfo.options().Bsymbolic() ||
- pLDInfo.options().hasNow()) {
- // TODO: add checks for DF_TEXTREL and DF_STATIC_TLS
+ if (pConfig.options().hasOrigin() ||
+ pConfig.options().Bsymbolic() ||
+ pConfig.options().hasNow() ||
+ m_Backend.hasTextRel() ||
+ (m_Backend.hasStaticTLS() &&
+ (LinkerConfig::DynObj == pConfig.codeGenType()))) {
reserveOne(llvm::ELF::DT_FLAGS); // DT_FLAGS
}
- if (pLDInfo.options().hasNow() ||
- pLDInfo.options().hasLoadFltr() ||
- pLDInfo.options().hasOrigin() ||
- pLDInfo.options().hasInterPose() ||
- pLDInfo.options().hasNoDefaultLib() ||
- pLDInfo.options().hasNoDump() ||
- pLDInfo.options().Bgroup() ||
- ((pLDInfo.output().type() == Output::DynObj) &&
- (pLDInfo.options().hasNoDelete() ||
- pLDInfo.options().hasInitFirst() ||
- pLDInfo.options().hasNoDLOpen()))) {
+ if (m_Backend.hasTextRel())
+ reserveOne(llvm::ELF::DT_TEXTREL); // DT_TEXTREL
+
+ if (pConfig.options().hasNow() ||
+ pConfig.options().hasLoadFltr() ||
+ pConfig.options().hasOrigin() ||
+ pConfig.options().hasInterPose() ||
+ pConfig.options().hasNoDefaultLib() ||
+ pConfig.options().hasNoDump() ||
+ pConfig.options().Bgroup() ||
+ ((LinkerConfig::DynObj == pConfig.codeGenType()) &&
+ (pConfig.options().hasNoDelete() ||
+ pConfig.options().hasInitFirst() ||
+ pConfig.options().hasNoDLOpen()))) {
reserveOne(llvm::ELF::DT_FLAGS_1); // DT_FLAGS_1
}
@@ -171,11 +177,11 @@
}
/// applyEntries - apply entries
-void ELFDynamic::applyEntries(const MCLDInfo& pInfo,
+void ELFDynamic::applyEntries(const LinkerConfig& pConfig,
const ELFFileFormat& pFormat)
{
- if (pInfo.output().type() == Output::DynObj &&
- pInfo.options().Bsymbolic()) {
+ if (LinkerConfig::DynObj == pConfig.codeGenType() &&
+ pConfig.options().Bsymbolic()) {
applyOne(llvm::ELF::DT_SYMBOLIC, 0x0); // DT_SYMBOLIC
}
@@ -238,39 +244,51 @@
applyOne(llvm::ELF::DT_RELAENT, m_pEntryFactory->relaSize()); // DT_RELAENT
}
+ if (m_Backend.hasTextRel()) {
+ applyOne(llvm::ELF::DT_TEXTREL, 0x0); // DT_TEXTREL
+
+ if (pConfig.options().warnSharedTextrel() &&
+ LinkerConfig::DynObj == pConfig.codeGenType())
+ mcld::warning(mcld::diag::warn_shared_textrel);
+ }
+
uint64_t dt_flags = 0x0;
- if (pInfo.options().hasOrigin())
+ if (pConfig.options().hasOrigin())
dt_flags |= llvm::ELF::DF_ORIGIN;
- if (pInfo.options().Bsymbolic())
+ if (pConfig.options().Bsymbolic())
dt_flags |= llvm::ELF::DF_SYMBOLIC;
- if (pInfo.options().hasNow())
+ if (pConfig.options().hasNow())
dt_flags |= llvm::ELF::DF_BIND_NOW;
- // TODO: add checks for DF_TEXTREL and DF_STATIC_TLS
+ if (m_Backend.hasTextRel())
+ dt_flags |= llvm::ELF::DF_TEXTREL;
+ if (m_Backend.hasStaticTLS() &&
+ (LinkerConfig::DynObj == pConfig.codeGenType()))
+ dt_flags |= llvm::ELF::DF_STATIC_TLS;
if (0x0 != dt_flags) {
applyOne(llvm::ELF::DT_FLAGS, dt_flags); // DT_FLAGS
}
uint64_t dt_flags_1 = 0x0;
- if (pInfo.options().hasNow())
+ if (pConfig.options().hasNow())
dt_flags_1 |= llvm::ELF::DF_1_NOW;
- if (pInfo.options().hasLoadFltr())
+ if (pConfig.options().hasLoadFltr())
dt_flags_1 |= llvm::ELF::DF_1_LOADFLTR;
- if (pInfo.options().hasOrigin())
+ if (pConfig.options().hasOrigin())
dt_flags_1 |= llvm::ELF::DF_1_ORIGIN;
- if (pInfo.options().hasInterPose())
+ if (pConfig.options().hasInterPose())
dt_flags_1 |= llvm::ELF::DF_1_INTERPOSE;
- if (pInfo.options().hasNoDefaultLib())
+ if (pConfig.options().hasNoDefaultLib())
dt_flags_1 |= llvm::ELF::DF_1_NODEFLIB;
- if (pInfo.options().hasNoDump())
+ if (pConfig.options().hasNoDump())
dt_flags_1 |= llvm::ELF::DF_1_NODUMP;
- if (pInfo.options().Bgroup())
+ if (pConfig.options().Bgroup())
dt_flags_1 |= llvm::ELF::DF_1_GROUP;
- if (pInfo.output().type() == Output::DynObj) {
- if (pInfo.options().hasNoDelete())
+ if (LinkerConfig::DynObj == pConfig.codeGenType()) {
+ if (pConfig.options().hasNoDelete())
dt_flags_1 |= llvm::ELF::DF_1_NODELETE;
- if (pInfo.options().hasInitFirst())
+ if (pConfig.options().hasInitFirst())
dt_flags_1 |= llvm::ELF::DF_1_INITFIRST;
- if (pInfo.options().hasNoDLOpen())
+ if (pConfig.options().hasNoDLOpen())
dt_flags_1 |= llvm::ELF::DF_1_NOOPEN;
}
if (0x0 != dt_flags_1)
diff --git a/lib/LD/ELFSectionMap.cpp b/lib/Target/ELFEmulation.cpp
similarity index 66%
copy from lib/LD/ELFSectionMap.cpp
copy to lib/Target/ELFEmulation.cpp
index 9d433d7..3bd2094 100644
--- a/lib/LD/ELFSectionMap.cpp
+++ b/lib/Target/ELFEmulation.cpp
@@ -1,4 +1,4 @@
-//===- ELFSectionMap.cpp --------------------------------------------------===//
+//===- ELFEmulation.cpp ---------------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,18 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/LD/ELFSectionMap.h>
+#include <mcld/Target/ELFEmulation.h>
+#include <mcld/LinkerConfig.h>
using namespace mcld;
struct NameMap {
- const char* from;
- const char* to;
+ const char* from; ///< the prefix of the input string. (match FROM*)
+ const char* to; ///< the output string.
};
-// Common mappings of ELF and other formants. Now only ELF specific mappings
-// are added
static const NameMap map[] =
{
{".text", ".text"},
@@ -33,55 +31,45 @@
// TODO: Support DT_INIT_ARRAY for all constructors?
{".ctors", ".ctors"},
{".dtors", ".dtors"},
- {".sdata", ".sdata"},
- {".sbss", ".sbss"},
// FIXME: in GNU ld, if we are creating a shared object .sdata2 and .sbss2
// sections would be handled differently.
{".sdata2", ".sdata"},
{".sbss2", ".sbss"},
+ {".sdata", ".sdata"},
+ {".sbss", ".sbss"},
{".lrodata", ".lrodata"},
{".ldata", ".ldata"},
{".lbss", ".lbss"},
{".gcc_except_table", ".gcc_except_table"},
{".gnu.linkonce.d.rel.ro.local", ".data.rel.ro.local"},
{".gnu.linkonce.d.rel.ro", ".data.rel.ro"},
- {".gnu.linkonce.t", ".text"},
{".gnu.linkonce.r", ".rodata"},
{".gnu.linkonce.d", ".data"},
{".gnu.linkonce.b", ".bss"},
- {".gnu.linkonce.s", ".sdata"},
+ {".gnu.linkonce.sb2", ".sbss"},
{".gnu.linkonce.sb", ".sbss"},
{".gnu.linkonce.s2", ".sdata"},
- {".gnu.linkonce.sb2", ".sbss"},
+ {".gnu.linkonce.s", ".sdata"},
{".gnu.linkonce.wi", ".debug_info"},
{".gnu.linkonce.td", ".tdata"},
{".gnu.linkonce.tb", ".tbss"},
+ {".gnu.linkonce.t", ".text"},
{".gnu.linkonce.lr", ".lrodata"},
- {".gnu.linkonce.l", ".ldata"},
{".gnu.linkonce.lb", ".lbss"},
+ {".gnu.linkonce.l", ".ldata"},
};
-static const int map_size = (sizeof(map) / sizeof(map[0]));
-
-ELFSectionMap::ELFSectionMap()
+bool mcld::MCLDEmulateELF(LinkerConfig& pConfig)
{
-}
-
-ELFSectionMap::~ELFSectionMap()
-{
-}
-
-void ELFSectionMap::initStandardMaps()
-{
- for (unsigned int i = 0; i < map_size; ++i) {
- bool exist = false;
- NamePair& pair = append(map[i].from, map[i].to, exist);
- if (exist) {
- warning(diag::warn_duplicate_std_sectmap) << map[i].from
- << map[i].to
- << pair.from
- << pair.to;
+ if (pConfig.codeGenType() != LinkerConfig::Object) {
+ const unsigned int map_size = (sizeof(map) / sizeof(map[0]) );
+ for (unsigned int i = 0; i < map_size; ++i) {
+ bool exist = false;
+ pConfig.scripts().sectionMap().append(map[i].from, map[i].to, exist);
+ if (exist)
+ return false;
}
}
+ return true;
}
diff --git a/lib/LD/ELFSectionMap.cpp b/lib/Target/ELFMCLinker.cpp
similarity index 67%
rename from lib/LD/ELFSectionMap.cpp
rename to lib/Target/ELFMCLinker.cpp
index 9d433d7..0c4d98f 100644
--- a/lib/LD/ELFSectionMap.cpp
+++ b/lib/Target/ELFMCLinker.cpp
@@ -1,4 +1,4 @@
-//===- ELFSectionMap.cpp --------------------------------------------------===//
+//===- ELFMCLinker.cpp ----------------------------------------------------===//
//
// The MCLinker Project
//
@@ -6,18 +6,18 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+#include <mcld/Target/ELFMCLinker.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/Object/SectionMap.h>
#include <mcld/Support/MsgHandling.h>
-#include <mcld/LD/ELFSectionMap.h>
using namespace mcld;
struct NameMap {
- const char* from;
- const char* to;
+ const char* from; ///< the prefix of the input string. (match FROM*)
+ const char* to; ///< the output string.
};
-// Common mappings of ELF and other formants. Now only ELF specific mappings
-// are added
static const NameMap map[] =
{
{".text", ".text"},
@@ -33,55 +33,46 @@
// TODO: Support DT_INIT_ARRAY for all constructors?
{".ctors", ".ctors"},
{".dtors", ".dtors"},
- {".sdata", ".sdata"},
- {".sbss", ".sbss"},
// FIXME: in GNU ld, if we are creating a shared object .sdata2 and .sbss2
// sections would be handled differently.
{".sdata2", ".sdata"},
{".sbss2", ".sbss"},
+ {".sdata", ".sdata"},
+ {".sbss", ".sbss"},
{".lrodata", ".lrodata"},
{".ldata", ".ldata"},
{".lbss", ".lbss"},
{".gcc_except_table", ".gcc_except_table"},
{".gnu.linkonce.d.rel.ro.local", ".data.rel.ro.local"},
{".gnu.linkonce.d.rel.ro", ".data.rel.ro"},
- {".gnu.linkonce.t", ".text"},
{".gnu.linkonce.r", ".rodata"},
{".gnu.linkonce.d", ".data"},
{".gnu.linkonce.b", ".bss"},
- {".gnu.linkonce.s", ".sdata"},
+ {".gnu.linkonce.sb2", ".sbss"},
{".gnu.linkonce.sb", ".sbss"},
{".gnu.linkonce.s2", ".sdata"},
- {".gnu.linkonce.sb2", ".sbss"},
+ {".gnu.linkonce.s", ".sdata"},
{".gnu.linkonce.wi", ".debug_info"},
{".gnu.linkonce.td", ".tdata"},
{".gnu.linkonce.tb", ".tbss"},
+ {".gnu.linkonce.t", ".text"},
{".gnu.linkonce.lr", ".lrodata"},
- {".gnu.linkonce.l", ".ldata"},
{".gnu.linkonce.lb", ".lbss"},
+ {".gnu.linkonce.l", ".ldata"},
};
-static const int map_size = (sizeof(map) / sizeof(map[0]));
+//===----------------------------------------------------------------------===//
+// ELFMCLinker
+//===----------------------------------------------------------------------===//
+ELFMCLinker::ELFMCLinker(LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ MemoryArea& pOutput)
+ : MCLinker(pConfig, pModule, pOutput) {
-ELFSectionMap::ELFSectionMap()
-{
}
-ELFSectionMap::~ELFSectionMap()
+ELFMCLinker::~ELFMCLinker()
{
-}
-
-void ELFSectionMap::initStandardMaps()
-{
- for (unsigned int i = 0; i < map_size; ++i) {
- bool exist = false;
- NamePair& pair = append(map[i].from, map[i].to, exist);
- if (exist) {
- warning(diag::warn_duplicate_std_sectmap) << map[i].from
- << map[i].to
- << pair.from
- << pair.to;
- }
- }
+ // MCLinker will delete m_pLDBackend and m_pLDDriver;
}
diff --git a/lib/Target/ELFSectLinker.cpp b/lib/Target/ELFSectLinker.cpp
deleted file mode 100644
index b95ed0b..0000000
--- a/lib/Target/ELFSectLinker.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===- ELFSectLinker.cpp ------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <mcld/Target/ELFSectLinker.h>
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-//==========================
-// ELFSectLinker
-ELFSectLinker::ELFSectLinker(SectLinkerOption &pOption,
- TargetLDBackend &pLDBackend)
- : SectLinker(pOption, pLDBackend) {
-}
-
-ELFSectLinker::~ELFSectLinker()
-{
- // SectLinker will delete m_pLDBackend and m_pLDDriver;
-}
-
diff --git a/lib/Target/GNULDBackend.cpp b/lib/Target/GNULDBackend.cpp
index f81133f..950ac43 100644
--- a/lib/Target/GNULDBackend.cpp
+++ b/lib/Target/GNULDBackend.cpp
@@ -6,45 +6,65 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#include <mcld/Target/GNULDBackend.h>
#include <string>
#include <cstring>
#include <cassert>
-#include <llvm/Support/ELF.h>
-
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/InputTree.h>
#include <mcld/ADT/SizeTraits.h>
#include <mcld/LD/LDSymbol.h>
-#include <mcld/LD/Layout.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/InputTree.h>
-#include <mcld/MC/SymbolCategory.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/LD/LDContext.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/LD/EhFrame.h>
+#include <mcld/LD/EhFrameHdr.h>
+#include <mcld/LD/RelocData.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/Support/MemoryArea.h>
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/LD/BranchIslandFactory.h>
+#include <mcld/LD/StubFactory.h>
+#include <mcld/Object/ObjectBuilder.h>
using namespace mcld;
+//===--------------------------------------------------------------------===//
+// non-member functions
+//===----------------------------------------------------------------------===//
+
+/// isCIdentifier - return if the pName is a valid C identifier
+static bool isCIdentifier(const std::string& pName)
+{
+ std::string ident = "0123456789"
+ "ABCDEFGHIJKLMNOPWRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "_";
+ return (pName.find_first_not_of(ident) > pName.length());
+}
+
//===----------------------------------------------------------------------===//
// GNULDBackend
//===----------------------------------------------------------------------===//
-GNULDBackend::GNULDBackend()
- : m_pArchiveReader(NULL),
+GNULDBackend::GNULDBackend(const LinkerConfig& pConfig)
+ : TargetLDBackend(pConfig),
m_pObjectReader(NULL),
- m_pDynObjReader(NULL),
- m_pObjectWriter(NULL),
- m_pDynObjWriter(NULL),
- m_pExecWriter(NULL),
m_pDynObjFileFormat(NULL),
m_pExecFileFormat(NULL),
+ m_pObjectFileFormat(NULL),
m_ELFSegmentTable(9), // magic number
+ m_pBRIslandFactory(NULL),
+ m_pStubFactory(NULL),
+ m_pEhFrame(NULL),
m_pEhFrameHdr(NULL),
+ m_bHasTextRel(false),
+ m_bHasStaticTLS(false),
f_pPreInitArrayStart(NULL),
f_pPreInitArrayEnd(NULL),
f_pInitArrayStart(NULL),
@@ -52,6 +72,9 @@
f_pFiniArrayStart(NULL),
f_pFiniArrayEnd(NULL),
f_pStack(NULL),
+ f_pDynamic(NULL),
+ f_pTDATA(NULL),
+ f_pTBSS(NULL),
f_pExecutableStart(NULL),
f_pEText(NULL),
f_p_EText(NULL),
@@ -66,26 +89,16 @@
GNULDBackend::~GNULDBackend()
{
- if (NULL != m_pArchiveReader)
- delete m_pArchiveReader;
- if (NULL != m_pObjectReader)
- delete m_pObjectReader;
- if (NULL != m_pDynObjReader)
- delete m_pDynObjReader;
- if (NULL != m_pObjectWriter)
- delete m_pObjectWriter;
- if (NULL != m_pDynObjWriter)
- delete m_pDynObjWriter;
- if (NULL != m_pExecWriter)
- delete m_pExecWriter;
- if (NULL != m_pDynObjFileFormat)
- delete m_pDynObjFileFormat;
- if (NULL != m_pExecFileFormat)
- delete m_pExecFileFormat;
- if (NULL != m_pSymIndexMap)
- delete m_pSymIndexMap;
- if (NULL != m_pEhFrameHdr)
- delete m_pEhFrameHdr;
+ delete m_pDynObjFileFormat;
+ delete m_pExecFileFormat;
+ delete m_pSymIndexMap;
+ delete m_pEhFrame;
+ delete m_pEhFrameHdr;
+
+ if (NULL != m_pBRIslandFactory)
+ delete m_pBRIslandFactory;
+ if (NULL != m_pStubFactory)
+ delete m_pStubFactory;
}
size_t GNULDBackend::sectionStartOffset() const
@@ -94,98 +107,153 @@
return sizeof(llvm::ELF::Elf64_Ehdr)+10*sizeof(llvm::ELF::Elf64_Phdr);
}
-uint64_t GNULDBackend::segmentStartAddr(const Output& pOutput,
- const MCLDInfo& pInfo) const
+uint64_t GNULDBackend::segmentStartAddr(const FragmentLinker& pLinker) const
{
- // TODO: handle the user option: -TText=
- if (isOutputPIC(pOutput, pInfo))
+ ScriptOptions::AddressMap::const_iterator mapping =
+ config().scripts().addressMap().find(".text");
+ if (mapping != config().scripts().addressMap().end())
+ return mapping.getEntry()->value();
+ else if (pLinker.isOutputPIC())
return 0x0;
else
return defaultTextSegmentAddr();
}
-bool GNULDBackend::initArchiveReader(MCLinker& pLinker,
- MCLDInfo& pInfo,
- MemoryAreaFactory& pMemAreaFactory)
+GNUArchiveReader*
+GNULDBackend::createArchiveReader(Module& pModule)
{
- if (NULL == m_pArchiveReader) {
- assert(NULL != m_pObjectReader);
- m_pArchiveReader = new GNUArchiveReader(pInfo,
- pMemAreaFactory,
- *m_pObjectReader);
+ assert(NULL != m_pObjectReader);
+ return new GNUArchiveReader(pModule, *m_pObjectReader);
+}
+
+ELFObjectReader* GNULDBackend::createObjectReader(FragmentLinker& pLinker)
+{
+ m_pObjectReader = new ELFObjectReader(*this, pLinker);
+ return m_pObjectReader;
+}
+
+ELFDynObjReader* GNULDBackend::createDynObjReader(FragmentLinker& pLinker)
+{
+ return new ELFDynObjReader(*this, pLinker);
+}
+
+ELFObjectWriter* GNULDBackend::createObjectWriter(FragmentLinker& pLinker)
+{
+ return new ELFObjectWriter(*this, pLinker);
+}
+
+ELFDynObjWriter* GNULDBackend::createDynObjWriter(FragmentLinker& pLinker)
+{
+ return new ELFDynObjWriter(*this, pLinker);
+}
+
+ELFExecWriter* GNULDBackend::createExecWriter(FragmentLinker& pLinker)
+{
+ return new ELFExecWriter(*this, pLinker);
+}
+
+bool GNULDBackend::initStdSections(ObjectBuilder& pBuilder)
+{
+ switch (config().codeGenType()) {
+ case LinkerConfig::DynObj: {
+ if (NULL == m_pDynObjFileFormat)
+ m_pDynObjFileFormat = new ELFDynObjFileFormat();
+ m_pDynObjFileFormat->initStdSections(pBuilder, bitclass());
+ return true;
+ }
+ case LinkerConfig::Exec: {
+ if (NULL == m_pExecFileFormat)
+ m_pExecFileFormat = new ELFExecFileFormat();
+ m_pExecFileFormat->initStdSections(pBuilder, bitclass());
+ return true;
+ }
+ case LinkerConfig::Object: {
+ if (NULL == m_pObjectFileFormat)
+ m_pObjectFileFormat = new ELFObjectFileFormat();
+ m_pObjectFileFormat->initStdSections(pBuilder, bitclass());
+ return true;
+ }
+ default:
+ fatal(diag::unrecognized_output_file) << config().codeGenType();
+ return false;
}
- return true;
}
-bool GNULDBackend::initObjectReader(MCLinker& pLinker)
+/// initStandardSymbols - define and initialize standard symbols.
+/// This function is called after section merging but before read relocations.
+bool GNULDBackend::initStandardSymbols(FragmentLinker& pLinker,
+ Module& pModule)
{
- if (NULL == m_pObjectReader)
- m_pObjectReader = new ELFObjectReader(*this, pLinker);
- return true;
-}
+ if (LinkerConfig::Object == config().codeGenType())
+ return true;
-bool GNULDBackend::initDynObjReader(MCLinker& pLinker)
-{
- if (NULL == m_pDynObjReader)
- m_pDynObjReader = new ELFDynObjReader(*this, pLinker);
- return true;
-}
+ // GNU extension: define __start and __stop symbols for the sections whose
+ // name can be presented as C symbol
+ // ref: GNU gold, Layout::define_section_symbols
+ Module::iterator iter, iterEnd = pModule.end();
+ for (iter = pModule.begin(); iter != iterEnd; ++iter) {
+ LDSection* section = *iter;
-bool GNULDBackend::initObjectWriter(MCLinker&)
-{
- // TODO
- return true;
-}
+ switch (section->kind()) {
+ case LDFileFormat::Relocation:
+ continue;
+ case LDFileFormat::EhFrame:
+ if (!section->hasEhFrame())
+ continue;
+ break;
+ default:
+ if (!section->hasSectionData())
+ continue;
+ break;
+ } // end of switch
-bool GNULDBackend::initDynObjWriter(MCLinker& pLinker)
-{
- if (NULL == m_pDynObjWriter)
- m_pDynObjWriter = new ELFDynObjWriter(*this, pLinker);
- return true;
-}
+ if (isCIdentifier(section->name())) {
+ llvm::StringRef start_name = llvm::StringRef("__start_" + section->name());
+ FragmentRef* start_fragref = FragmentRef::Create(
+ section->getSectionData()->front(), 0x0);
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>(start_name,
+ false, // isDyn
+ ResolveInfo::NoType,
+ ResolveInfo::Define,
+ ResolveInfo::Global,
+ 0x0, // size
+ 0x0, // value
+ start_fragref, // FragRef
+ ResolveInfo::Default);
-bool GNULDBackend::initExecWriter(MCLinker& pLinker)
-{
- if (NULL == m_pExecWriter)
- m_pExecWriter = new ELFExecWriter(*this, pLinker);
- return true;
-}
+ llvm::StringRef stop_name = llvm::StringRef("__stop_" + section->name());
+ FragmentRef* stop_fragref = FragmentRef::Create(
+ section->getSectionData()->front(), section->size());
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>(stop_name,
+ false, // isDyn
+ ResolveInfo::NoType,
+ ResolveInfo::Define,
+ ResolveInfo::Global,
+ 0x0, // size
+ 0x0, // value
+ stop_fragref, // FragRef
+ ResolveInfo::Default);
+ }
+ }
-bool GNULDBackend::initExecSections(MCLinker& pMCLinker)
-{
- if (NULL == m_pExecFileFormat)
- m_pExecFileFormat = new ELFExecFileFormat(*this);
-
- // initialize standard sections
- m_pExecFileFormat->initStdSections(pMCLinker);
- return true;
-}
-
-bool GNULDBackend::initDynObjSections(MCLinker& pMCLinker)
-{
- if (NULL == m_pDynObjFileFormat)
- m_pDynObjFileFormat = new ELFDynObjFileFormat(*this);
-
- // initialize standard sections
- m_pDynObjFileFormat->initStdSections(pMCLinker);
- return true;
-}
-
-bool GNULDBackend::initStandardSymbols(MCLinker& pLinker, const Output& pOutput)
-{
- ELFFileFormat* file_format = getOutputFormat(pOutput);
+ ELFFileFormat* file_format = getOutputFormat();
// ----- section symbols ----- //
// .preinit_array
FragmentRef* preinit_array = NULL;
if (file_format->hasPreInitArray()) {
- preinit_array = pLinker.getLayout().getFragmentRef(
- *(file_format->getPreInitArray().getSectionData()->begin()),
+ preinit_array = FragmentRef::Create(
+ file_format->getPreInitArray().getSectionData()->front(),
0x0);
}
+ else {
+ preinit_array = FragmentRef::Null();
+ }
f_pPreInitArrayStart =
- pLinker.defineSymbol<MCLinker::AsRefered,
- MCLinker::Resolve>("__preinit_array_start",
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("__preinit_array_start",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
@@ -195,28 +263,31 @@
preinit_array, // FragRef
ResolveInfo::Hidden);
f_pPreInitArrayEnd =
- pLinker.defineSymbol<MCLinker::AsRefered,
- MCLinker::Resolve>("__preinit_array_end",
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("__preinit_array_end",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
ResolveInfo::Global,
0x0, // size
0x0, // value
- NULL, // FragRef
+ FragmentRef::Null(), // FragRef
ResolveInfo::Hidden);
// .init_array
FragmentRef* init_array = NULL;
if (file_format->hasInitArray()) {
- init_array = pLinker.getLayout().getFragmentRef(
- *(file_format->getInitArray().getSectionData()->begin()),
+ init_array = FragmentRef::Create(
+ file_format->getInitArray().getSectionData()->front(),
0x0);
}
+ else {
+ init_array = FragmentRef::Null();
+ }
f_pInitArrayStart =
- pLinker.defineSymbol<MCLinker::AsRefered,
- MCLinker::Resolve>("__init_array_start",
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("__init_array_start",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
@@ -226,8 +297,8 @@
init_array, // FragRef
ResolveInfo::Hidden);
f_pInitArrayEnd =
- pLinker.defineSymbol<MCLinker::AsRefered,
- MCLinker::Resolve>("__init_array_end",
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("__init_array_end",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
@@ -240,14 +311,17 @@
// .fini_array
FragmentRef* fini_array = NULL;
if (file_format->hasFiniArray()) {
- fini_array = pLinker.getLayout().getFragmentRef(
- *(file_format->getFiniArray().getSectionData()->begin()),
+ fini_array = FragmentRef::Create(
+ file_format->getFiniArray().getSectionData()->front(),
0x0);
}
+ else {
+ fini_array = FragmentRef::Null();
+ }
f_pFiniArrayStart =
- pLinker.defineSymbol<MCLinker::AsRefered,
- MCLinker::Resolve>("__fini_array_start",
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("__fini_array_start",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
@@ -257,8 +331,8 @@
fini_array, // FragRef
ResolveInfo::Hidden);
f_pFiniArrayEnd =
- pLinker.defineSymbol<MCLinker::AsRefered,
- MCLinker::Resolve>("__fini_array_end",
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("__fini_array_end",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
@@ -271,13 +345,17 @@
// .stack
FragmentRef* stack = NULL;
if (file_format->hasStack()) {
- stack = pLinker.getLayout().getFragmentRef(
- *(file_format->getStack().getSectionData()->begin()),
+ stack = FragmentRef::Create(
+ file_format->getStack().getSectionData()->front(),
0x0);
}
+ else {
+ stack = FragmentRef::Null();
+ }
+
f_pStack =
- pLinker.defineSymbol<MCLinker::AsRefered,
- MCLinker::Resolve>("__stack",
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("__stack",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
@@ -287,124 +365,142 @@
stack, // FragRef
ResolveInfo::Hidden);
+ // _DYNAMIC
+ // TODO: add SectionData for .dynamic section, and then we can get the correct
+ // symbol section index for _DYNAMIC. Now it will be ABS.
+ f_pDynamic =
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("_DYNAMIC",
+ false, // isDyn
+ ResolveInfo::Object,
+ ResolveInfo::Define,
+ ResolveInfo::Local,
+ 0x0, // size
+ 0x0, // value
+ FragmentRef::Null(), // FragRef
+ ResolveInfo::Hidden);
+
// ----- segment symbols ----- //
f_pExecutableStart =
- pLinker.defineSymbol<MCLinker::AsRefered,
- MCLinker::Resolve>("__executable_start",
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("__executable_start",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
ResolveInfo::Absolute,
0x0, // size
0x0, // value
- NULL, // FragRef
+ FragmentRef::Null(), // FragRef
ResolveInfo::Default);
f_pEText =
- pLinker.defineSymbol<MCLinker::AsRefered,
- MCLinker::Resolve>("etext",
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("etext",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
ResolveInfo::Absolute,
0x0, // size
0x0, // value
- NULL, // FragRef
+ FragmentRef::Null(), // FragRef
ResolveInfo::Default);
f_p_EText =
- pLinker.defineSymbol<MCLinker::AsRefered,
- MCLinker::Resolve>("_etext",
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("_etext",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
ResolveInfo::Absolute,
0x0, // size
0x0, // value
- NULL, // FragRef
+ FragmentRef::Null(), // FragRef
ResolveInfo::Default);
f_p__EText =
- pLinker.defineSymbol<MCLinker::AsRefered,
- MCLinker::Resolve>("__etext",
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("__etext",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
ResolveInfo::Absolute,
0x0, // size
0x0, // value
- NULL, // FragRef
+ FragmentRef::Null(), // FragRef
ResolveInfo::Default);
f_pEData =
- pLinker.defineSymbol<MCLinker::AsRefered,
- MCLinker::Resolve>("edata",
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("edata",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
ResolveInfo::Absolute,
0x0, // size
0x0, // value
- NULL, // FragRef
+ FragmentRef::Null(), // FragRef
ResolveInfo::Default);
f_pEnd =
- pLinker.defineSymbol<MCLinker::AsRefered,
- MCLinker::Resolve>("end",
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("end",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
ResolveInfo::Absolute,
0x0, // size
0x0, // value
- NULL, // FragRef
+ FragmentRef::Null(), // FragRef
ResolveInfo::Default);
// _edata is defined forcefully.
// @ref Google gold linker: defstd.cc: 186
f_p_EData =
- pLinker.defineSymbol<MCLinker::Force,
- MCLinker::Resolve>("_edata",
+ pLinker.defineSymbol<FragmentLinker::Force,
+ FragmentLinker::Resolve>("_edata",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
ResolveInfo::Absolute,
0x0, // size
0x0, // value
- NULL, // FragRef
+ FragmentRef::Null(), // FragRef
ResolveInfo::Default);
// __bss_start is defined forcefully.
// @ref Google gold linker: defstd.cc: 214
f_pBSSStart =
- pLinker.defineSymbol<MCLinker::Force,
- MCLinker::Resolve>("__bss_start",
+ pLinker.defineSymbol<FragmentLinker::Force,
+ FragmentLinker::Resolve>("__bss_start",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
ResolveInfo::Absolute,
0x0, // size
0x0, // value
- NULL, // FragRef
+ FragmentRef::Null(), // FragRef
ResolveInfo::Default);
// _end is defined forcefully.
// @ref Google gold linker: defstd.cc: 228
f_p_End =
- pLinker.defineSymbol<MCLinker::Force,
- MCLinker::Resolve>("_end",
+ pLinker.defineSymbol<FragmentLinker::Force,
+ FragmentLinker::Resolve>("_end",
false, // isDyn
ResolveInfo::NoType,
ResolveInfo::Define,
ResolveInfo::Absolute,
0x0, // size
0x0, // value
- NULL, // FragRef
+ FragmentRef::Null(), // FragRef
ResolveInfo::Default);
return true;
}
bool
-GNULDBackend::finalizeStandardSymbols(MCLinker& pLinker, const Output& pOutput)
+GNULDBackend::finalizeStandardSymbols(FragmentLinker& pLinker)
{
- ELFFileFormat* file_format = getOutputFormat(pOutput);
+ if (LinkerConfig::Object == config().codeGenType())
+ return true;
+
+ ELFFileFormat* file_format = getOutputFormat();
// ----- section symbols ----- //
if (NULL != f_pPreInitArrayStart) {
@@ -468,6 +564,12 @@
}
}
+ if (NULL != f_pDynamic) {
+ f_pDynamic->resolveInfo()->setBinding(ResolveInfo::Local);
+ f_pDynamic->setValue(file_format->getDynamic().addr());
+ f_pDynamic->setSize(file_format->getDynamic().size());
+ }
+
// ----- segment symbols ----- //
if (NULL != f_pExecutableStart) {
ELFSegment* exec_start = m_ELFSegmentTable.find(llvm::ELF::PT_LOAD, 0x0, 0x0);
@@ -563,200 +665,185 @@
return true;
}
-GNUArchiveReader *GNULDBackend::getArchiveReader()
+bool GNULDBackend::finalizeTLSSymbol(LDSymbol& pSymbol)
{
- assert(NULL != m_pArchiveReader);
- return m_pArchiveReader;
+ // ignore if symbol has no fragRef
+ if (!pSymbol.hasFragRef())
+ return true;
+
+ // the value of a TLS symbol is the offset to the TLS segment
+ ELFSegment* tls_seg = m_ELFSegmentTable.find(llvm::ELF::PT_TLS,
+ llvm::ELF::PF_R, 0x0);
+ uint64_t value = pSymbol.fragRef()->getOutputOffset();
+ uint64_t addr = pSymbol.fragRef()->frag()->getParent()->getSection().addr();
+ pSymbol.setValue(value + addr - tls_seg->vaddr());
+ return true;
}
-const GNUArchiveReader *GNULDBackend::getArchiveReader() const
+ELFFileFormat* GNULDBackend::getOutputFormat()
{
- assert(NULL != m_pArchiveReader);
- return m_pArchiveReader;
-}
-
-ELFObjectReader *GNULDBackend::getObjectReader()
-{
- assert(NULL != m_pObjectReader);
- return m_pObjectReader;
-}
-
-const ELFObjectReader *GNULDBackend::getObjectReader() const
-{
- assert(NULL != m_pObjectReader);
- return m_pObjectReader;
-}
-
-ELFDynObjReader *GNULDBackend::getDynObjReader()
-{
- assert(NULL != m_pDynObjReader);
- return m_pDynObjReader;
-}
-
-const ELFDynObjReader *GNULDBackend::getDynObjReader() const
-{
- assert(NULL != m_pDynObjReader);
- return m_pDynObjReader;
-}
-
-ELFObjectWriter *GNULDBackend::getObjectWriter()
-{
- // TODO
- return NULL;
-}
-
-const ELFObjectWriter *GNULDBackend::getObjectWriter() const
-{
- // TODO
- return NULL;
-}
-
-ELFDynObjWriter *GNULDBackend::getDynObjWriter()
-{
- assert(NULL != m_pDynObjWriter);
- return m_pDynObjWriter;
-}
-
-const ELFDynObjWriter *GNULDBackend::getDynObjWriter() const
-{
- assert(NULL != m_pDynObjWriter);
- return m_pDynObjWriter;
-}
-
-ELFExecWriter *GNULDBackend::getExecWriter()
-{
- assert(NULL != m_pExecWriter);
- return m_pExecWriter;
-}
-
-const ELFExecWriter *GNULDBackend::getExecWriter() const
-{
- assert(NULL != m_pExecWriter);
- return m_pExecWriter;
-}
-
-ELFFileFormat* GNULDBackend::getOutputFormat(const Output& pOutput)
-{
- switch (pOutput.type()) {
- case Output::DynObj:
- return getDynObjFileFormat();
- case Output::Exec:
- return getExecFileFormat();
- // FIXME: We do not support building .o now
- case Output::Object:
+ switch (config().codeGenType()) {
+ case LinkerConfig::DynObj:
+ assert(NULL != m_pDynObjFileFormat);
+ return m_pDynObjFileFormat;
+ case LinkerConfig::Exec:
+ assert(NULL != m_pExecFileFormat);
+ return m_pExecFileFormat;
+ case LinkerConfig::Object:
+ assert(NULL != m_pObjectFileFormat);
+ return m_pObjectFileFormat;
default:
- fatal(diag::unrecognized_output_file) << pOutput.type();
+ fatal(diag::unrecognized_output_file) << config().codeGenType();
return NULL;
}
}
-const ELFFileFormat* GNULDBackend::getOutputFormat(const Output& pOutput) const
+const ELFFileFormat* GNULDBackend::getOutputFormat() const
{
- switch (pOutput.type()) {
- case Output::DynObj:
- return getDynObjFileFormat();
- case Output::Exec:
- return getExecFileFormat();
- // FIXME: We do not support building .o now
- case Output::Object:
+ switch (config().codeGenType()) {
+ case LinkerConfig::DynObj:
+ assert(NULL != m_pDynObjFileFormat);
+ return m_pDynObjFileFormat;
+ case LinkerConfig::Exec:
+ assert(NULL != m_pExecFileFormat);
+ return m_pExecFileFormat;
+ case LinkerConfig::Object:
+ assert(NULL != m_pObjectFileFormat);
+ return m_pObjectFileFormat;
default:
- fatal(diag::unrecognized_output_file) << pOutput.type();
+ fatal(diag::unrecognized_output_file) << config().codeGenType();
return NULL;
}
}
-ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat()
+void GNULDBackend::partialScanRelocation(Relocation& pReloc,
+ FragmentLinker& pLinker,
+ Module& pModule,
+ const LDSection& pSection)
{
- assert(NULL != m_pDynObjFileFormat);
- return m_pDynObjFileFormat;
-}
+ // if we meet a section symbol
+ if (pReloc.symInfo()->type() == ResolveInfo::Section) {
+ LDSymbol* input_sym = pReloc.symInfo()->outSymbol();
-const ELFDynObjFileFormat* GNULDBackend::getDynObjFileFormat() const
-{
- assert(NULL != m_pDynObjFileFormat);
- return m_pDynObjFileFormat;
-}
+ // 1. update the relocation target offset
+ assert(input_sym->hasFragRef());
+ uint64_t offset = input_sym->fragRef()->getOutputOffset();
+ pReloc.target() += offset;
-ELFExecFileFormat* GNULDBackend::getExecFileFormat()
-{
- assert(NULL != m_pExecFileFormat);
- return m_pExecFileFormat;
-}
-
-const ELFExecFileFormat* GNULDBackend::getExecFileFormat() const
-{
- assert(NULL != m_pExecFileFormat);
- return m_pExecFileFormat;
+ // 2. get output section symbol
+ // get the output LDSection which the symbol defined in
+ const LDSection& out_sect =
+ input_sym->fragRef()->frag()->getParent()->getSection();
+ ResolveInfo* sym_info = pModule.getSectionSymbolSet().get(out_sect)->resolveInfo();
+ // set relocation target symbol to the output section symbol's resolveInfo
+ pReloc.setSymInfo(sym_info);
+ }
}
/// sizeNamePools - compute the size of regular name pools
/// In ELF executable files, regular name pools are .symtab, .strtab,
-/// .dynsym, .dynstr, and .hash
+/// .dynsym, .dynstr, .hash and .shstrtab.
void
-GNULDBackend::sizeNamePools(const Output& pOutput,
- const SymbolCategory& pSymbols,
- const MCLDInfo& pLDInfo)
+GNULDBackend::sizeNamePools(const Module& pModule, bool pIsStaticLink)
{
- // size of string tables starts from 1 to hold the null character in their
- // first byte
- size_t symtab = 1;
- size_t dynsym = 1;
// number of entries in symbol tables starts from 1 to hold the special entry
// at index 0 (STN_UNDEF). See ELF Spec Book I, p1-21.
+ size_t symtab = 1;
+ size_t dynsym = pIsStaticLink ? 0 : 1;
+
+ // size of string tables starts from 1 to hold the null character in their
+ // first byte
size_t strtab = 1;
- size_t dynstr = 1;
+ size_t dynstr = pIsStaticLink ? 0 : 1;
+ size_t shstrtab = 1;
size_t hash = 0;
- // compute size of .symtab, .dynsym and .strtab
- SymbolCategory::const_iterator symbol;
- SymbolCategory::const_iterator symEnd = pSymbols.end();
- for (symbol = pSymbols.begin(); symbol != symEnd; ++symbol) {
- size_t str_size = (*symbol)->nameSize() + 1;
- if (isDynamicSymbol(**symbol, pOutput)) {
+ /// compute the size of .symtab, .dynsym and .strtab
+ /// @{
+ Module::const_sym_iterator symbol;
+ const Module::SymbolTable& symbols = pModule.getSymbolTable();
+ size_t str_size = 0;
+ // compute the size of symbols in Local and File category
+ Module::const_sym_iterator symEnd = symbols.localEnd();
+ for (symbol = symbols.localBegin(); symbol != symEnd; ++symbol) {
+ str_size = (*symbol)->nameSize() + 1;
+ if (!pIsStaticLink && isDynamicSymbol(**symbol)) {
++dynsym;
- dynstr += str_size;
+ if (ResolveInfo::Section != (*symbol)->type())
+ dynstr += str_size;
}
++symtab;
- strtab += str_size;
+ if (ResolveInfo::Section != (*symbol)->type())
+ strtab += str_size;
+ }
+ // compute the size of symbols in TLS category
+ symEnd = symbols.tlsEnd();
+ for (symbol = symbols.tlsBegin(); symbol != symEnd; ++symbol) {
+ str_size = (*symbol)->nameSize() + 1;
+ if (!pIsStaticLink) {
+ ++dynsym;
+ if (ResolveInfo::Section != (*symbol)->type())
+ dynstr += str_size;
+ }
+ ++symtab;
+ if (ResolveInfo::Section != (*symbol)->type())
+ strtab += str_size;
+ }
+ // compute the size of the reset of symbols
+ symEnd = pModule.sym_end();
+ for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
+ str_size = (*symbol)->nameSize() + 1;
+ if (!pIsStaticLink && isDynamicSymbol(**symbol)) {
+ ++dynsym;
+ if (ResolveInfo::Section != (*symbol)->type())
+ dynstr += str_size;
+ }
+ ++symtab;
+ if (ResolveInfo::Section != (*symbol)->type())
+ strtab += str_size;
}
- ELFFileFormat* file_format = getOutputFormat(pOutput);
+ ELFFileFormat* file_format = getOutputFormat();
- switch(pOutput.type()) {
+ switch(config().codeGenType()) {
// compute size of .dynstr and .hash
- case Output::DynObj:
- case Output::Exec: {
+ case LinkerConfig::DynObj: {
+ // soname
+ if (!pIsStaticLink)
+ dynstr += pModule.name().size() + 1;
+ }
+ /** fall through **/
+ case LinkerConfig::Exec: {
// add DT_NEED strings into .dynstr and .dynamic
// Rules:
// 1. ignore --no-add-needed
// 2. force count in --no-as-needed
// 3. judge --as-needed
- InputTree::const_bfs_iterator input, inputEnd = pLDInfo.inputs().bfs_end();
- for (input = pLDInfo.inputs().bfs_begin(); input != inputEnd; ++input) {
- if (Input::DynObj == (*input)->type()) {
+ if (!pIsStaticLink) {
+ Module::const_lib_iterator lib, libEnd = pModule.lib_end();
+ for (lib = pModule.lib_begin(); lib != libEnd; ++lib) {
// --add-needed
- if ((*input)->attribute()->isAddNeeded()) {
+ if ((*lib)->attribute()->isAddNeeded()) {
// --no-as-needed
- if (!(*input)->attribute()->isAsNeeded()) {
- dynstr += (*input)->name().size() + 1;
+ if (!(*lib)->attribute()->isAsNeeded()) {
+ dynstr += (*lib)->name().size() + 1;
dynamic().reserveNeedEntry();
}
// --as-needed
- else if ((*input)->isNeeded()) {
- dynstr += (*input)->name().size() + 1;
+ else if ((*lib)->isNeeded()) {
+ dynstr += (*lib)->name().size() + 1;
dynamic().reserveNeedEntry();
}
}
}
- } // for
- // compute .hash
- // Both Elf32_Word and Elf64_Word are 4 bytes
- hash = (2 + getHashBucketCount(dynsym, false) + dynsym) *
- sizeof(llvm::ELF::Elf32_Word);
+ // compute .hash
+ // Both Elf32_Word and Elf64_Word are 4 bytes
+ hash = (2 + getHashBucketCount(dynsym, false) + dynsym) *
+ sizeof(llvm::ELF::Elf32_Word);
+ }
// set size
- dynstr += pOutput.name().size() + 1;
if (32 == bitclass())
file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf32_Sym));
else
@@ -766,7 +853,7 @@
}
/* fall through */
- case Output::Object: {
+ case LinkerConfig::Object: {
if (32 == bitclass())
file_format->getSymTab().setSize(symtab*sizeof(llvm::ELF::Elf32_Sym));
else
@@ -774,50 +861,97 @@
file_format->getStrTab().setSize(strtab);
break;
}
+ default:
+ fatal(diag::fatal_illegal_codegen_type) << pModule.name();
+ break;
} // end of switch
+ /// @}
- // reserve fixed entries in the .dynamic section.
- if (Output::DynObj == pOutput.type() || Output::Exec == pOutput.type()) {
+ /// reserve fixed entries in the .dynamic section.
+ /// @{
+ if (LinkerConfig::DynObj == config().codeGenType() ||
+ LinkerConfig::Exec == config().codeGenType()) {
// Because some entries in .dynamic section need information of .dynsym,
// .dynstr, .symtab, .strtab and .hash, we can not reserve non-DT_NEEDED
// entries until we get the size of the sections mentioned above
- dynamic().reserveEntries(pLDInfo, *file_format);
+ if (!pIsStaticLink)
+ dynamic().reserveEntries(config(), *file_format);
file_format->getDynamic().setSize(dynamic().numOfBytes());
}
+ /// @}
+
+ /// compute the size of .shstrtab section.
+ /// @{
+ Module::const_iterator sect, sectEnd = pModule.end();
+ for (sect = pModule.begin(); sect != sectEnd; ++sect) {
+ // StackNote sections will always be in output!
+ if (0 != (*sect)->size() || LDFileFormat::StackNote == (*sect)->kind()) {
+ shstrtab += ((*sect)->name().size() + 1);
+ }
+ }
+ shstrtab += (strlen(".shstrtab") + 1);
+ file_format->getShStrTab().setSize(shstrtab);
+ /// @}
+}
+
+/// emitSymbol32 - emit an ELF32 symbol
+void GNULDBackend::emitSymbol32(llvm::ELF::Elf32_Sym& pSym,
+ LDSymbol& pSymbol,
+ char* pStrtab,
+ size_t pStrtabsize,
+ size_t pSymtabIdx)
+{
+ // FIXME: check the endian between host and target
+ // write out symbol
+ if (ResolveInfo::Section != pSymbol.type()) {
+ pSym.st_name = pStrtabsize;
+ strcpy((pStrtab + pStrtabsize), pSymbol.name());
+ }
+ else {
+ pSym.st_name = 0;
+ }
+ pSym.st_value = pSymbol.value();
+ pSym.st_size = getSymbolSize(pSymbol);
+ pSym.st_info = getSymbolInfo(pSymbol);
+ pSym.st_other = pSymbol.visibility();
+ pSym.st_shndx = getSymbolShndx(pSymbol);
+}
+
+/// emitSymbol64 - emit an ELF64 symbol
+void GNULDBackend::emitSymbol64(llvm::ELF::Elf64_Sym& pSym,
+ LDSymbol& pSymbol,
+ char* pStrtab,
+ size_t pStrtabsize,
+ size_t pSymtabIdx)
+{
+ // FIXME: check the endian between host and target
+ // write out symbol
+ pSym.st_name = pStrtabsize;
+ pSym.st_value = pSymbol.value();
+ pSym.st_size = getSymbolSize(pSymbol);
+ pSym.st_info = getSymbolInfo(pSymbol);
+ pSym.st_other = pSymbol.visibility();
+ pSym.st_shndx = getSymbolShndx(pSymbol);
+ // write out string
+ strcpy((pStrtab + pStrtabsize), pSymbol.name());
}
/// emitRegNamePools - emit regular name pools - .symtab, .strtab
///
/// the size of these tables should be computed before layout
/// layout should computes the start offset of these tables
-void GNULDBackend::emitRegNamePools(Output& pOutput,
- SymbolCategory& pSymbols,
- const Layout& pLayout,
- const MCLDInfo& pLDInfo)
+void GNULDBackend::emitRegNamePools(const Module& pModule,
+ MemoryArea& pOutput)
{
-
- assert(pOutput.hasMemArea());
-
- bool sym_exist = false;
- HashTableType::entry_type* entry = 0;
-
- ELFFileFormat* file_format = getOutputFormat(pOutput);
- if (pOutput.type() == Output::Object) {
- // add first symbol into m_pSymIndexMap
- entry = m_pSymIndexMap->insert(NULL, sym_exist);
- entry->setValue(0);
-
- // TODO: not support yet
- return;
- }
+ ELFFileFormat* file_format = getOutputFormat();
LDSection& symtab_sect = file_format->getSymTab();
LDSection& strtab_sect = file_format->getStrTab();
- MemoryRegion* symtab_region = pOutput.memArea()->request(symtab_sect.offset(),
- symtab_sect.size());
- MemoryRegion* strtab_region = pOutput.memArea()->request(strtab_sect.offset(),
- strtab_sect.size());
+ MemoryRegion* symtab_region = pOutput.request(symtab_sect.offset(),
+ symtab_sect.size());
+ MemoryRegion* strtab_region = pOutput.request(strtab_sect.offset(),
+ strtab_sect.size());
// set up symtab_region
llvm::ELF::Elf32_Sym* symtab32 = NULL;
@@ -852,58 +986,52 @@
symtab64[0].st_shndx = 0;
}
+ bool sym_exist = false;
+ HashTableType::entry_type* entry = NULL;
+ if (LinkerConfig::Object == config().codeGenType()) {
+ entry = m_pSymIndexMap->insert(NULL, sym_exist);
+ entry->setValue(0);
+ }
+
size_t symtabIdx = 1;
size_t strtabsize = 1;
// compute size of .symtab, .dynsym and .strtab
- SymbolCategory::iterator symbol;
- SymbolCategory::iterator symEnd = pSymbols.end();
- for (symbol = pSymbols.begin(); symbol != symEnd; ++symbol) {
-
- // maintain output's symbol and index map if building .o file
- if (Output::Object == pOutput.type()) {
- entry = m_pSymIndexMap->insert(NULL, sym_exist);
+ Module::const_sym_iterator symbol;
+ Module::const_sym_iterator symEnd = pModule.sym_end();
+ for (symbol = pModule.sym_begin(); symbol != symEnd; ++symbol) {
+ // maintain output's symbol and index map if building .o file
+ if (LinkerConfig::Object == config().codeGenType()) {
+ entry = m_pSymIndexMap->insert(*symbol, sym_exist);
entry->setValue(symtabIdx);
}
- // FIXME: check the endian between host and target
- // write out symbol
- if (32 == bitclass()) {
- symtab32[symtabIdx].st_name = strtabsize;
- symtab32[symtabIdx].st_value = getSymbolValue(**symbol);
- symtab32[symtabIdx].st_size = getSymbolSize(**symbol);
- symtab32[symtabIdx].st_info = getSymbolInfo(**symbol);
- symtab32[symtabIdx].st_other = (*symbol)->visibility();
- symtab32[symtabIdx].st_shndx = getSymbolShndx(**symbol, pLayout);
- }
- else { // must 64
- symtab64[symtabIdx].st_name = strtabsize;
- symtab64[symtabIdx].st_value = getSymbolValue(**symbol);
- symtab64[symtabIdx].st_size = getSymbolSize(**symbol);
- symtab64[symtabIdx].st_info = getSymbolInfo(**symbol);
- symtab64[symtabIdx].st_other = (*symbol)->visibility();
- symtab64[symtabIdx].st_shndx = getSymbolShndx(**symbol, pLayout);
- }
- // write out string
- strcpy((strtab + strtabsize), (*symbol)->name());
+ if (32 == bitclass())
+ emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+ symtabIdx);
+ else
+ emitSymbol64(symtab64[symtabIdx], **symbol, strtab, strtabsize,
+ symtabIdx);
- // write out
// sum up counters
++symtabIdx;
- strtabsize += (*symbol)->nameSize() + 1;
+ if (ResolveInfo::Section != (*symbol)->type())
+ strtabsize += (*symbol)->nameSize() + 1;
}
}
-/// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
+/// emitDynNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
///
/// the size of these tables should be computed before layout
/// layout should computes the start offset of these tables
-void GNULDBackend::emitDynNamePools(Output& pOutput,
- SymbolCategory& pSymbols,
- const Layout& pLayout,
- const MCLDInfo& pLDInfo)
+void GNULDBackend::emitDynNamePools(const Module& pModule,
+ MemoryArea& pOutput)
{
- assert(pOutput.hasMemArea());
- ELFFileFormat* file_format = getOutputFormat(pOutput);
+ ELFFileFormat* file_format = getOutputFormat();
+ if (!file_format->hasDynSymTab() ||
+ !file_format->hasDynStrTab() ||
+ !file_format->hasHashTab() ||
+ !file_format->hasDynamic())
+ return;
bool sym_exist = false;
HashTableType::entry_type* entry = 0;
@@ -913,14 +1041,14 @@
LDSection& hash_sect = file_format->getHashTab();
LDSection& dyn_sect = file_format->getDynamic();
- MemoryRegion* symtab_region = pOutput.memArea()->request(symtab_sect.offset(),
- symtab_sect.size());
- MemoryRegion* strtab_region = pOutput.memArea()->request(strtab_sect.offset(),
- strtab_sect.size());
- MemoryRegion* hash_region = pOutput.memArea()->request(hash_sect.offset(),
- hash_sect.size());
- MemoryRegion* dyn_region = pOutput.memArea()->request(dyn_sect.offset(),
- dyn_sect.size());
+ MemoryRegion* symtab_region = pOutput.request(symtab_sect.offset(),
+ symtab_sect.size());
+ MemoryRegion* strtab_region = pOutput.request(strtab_sect.offset(),
+ strtab_sect.size());
+ MemoryRegion* hash_region = pOutput.request(hash_sect.offset(),
+ hash_sect.size());
+ MemoryRegion* dyn_region = pOutput.request(dyn_sect.offset(),
+ dyn_sect.size());
// set up symtab_region
llvm::ELF::Elf32_Sym* symtab32 = NULL;
llvm::ELF::Elf64_Sym* symtab64 = NULL;
@@ -962,40 +1090,69 @@
size_t strtabsize = 1;
// emit of .dynsym, and .dynstr
- SymbolCategory::iterator symbol;
- SymbolCategory::iterator symEnd = pSymbols.end();
- for (symbol = pSymbols.begin(); symbol != symEnd; ++symbol) {
- if (!isDynamicSymbol(**symbol, pOutput))
+ Module::const_sym_iterator symbol;
+ const Module::SymbolTable& symbols = pModule.getSymbolTable();
+ // emit symbol in File and Local category if it's dynamic symbol
+ Module::const_sym_iterator symEnd = symbols.localEnd();
+ for (symbol = symbols.localBegin(); symbol != symEnd; ++symbol) {
+ if (!isDynamicSymbol(**symbol))
continue;
+ if (32 == bitclass())
+ emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+ symtabIdx);
+ else
+ emitSymbol64(symtab64[symtabIdx], **symbol, strtab, strtabsize,
+ symtabIdx);
+
// maintain output's symbol and index map
entry = m_pSymIndexMap->insert(*symbol, sym_exist);
entry->setValue(symtabIdx);
-
- // FIXME: check the endian between host and target
- // write out symbol
- if (32 == bitclass()) {
- symtab32[symtabIdx].st_name = strtabsize;
- symtab32[symtabIdx].st_value = (*symbol)->value();
- symtab32[symtabIdx].st_size = getSymbolSize(**symbol);
- symtab32[symtabIdx].st_info = getSymbolInfo(**symbol);
- symtab32[symtabIdx].st_other = (*symbol)->visibility();
- symtab32[symtabIdx].st_shndx = getSymbolShndx(**symbol, pLayout);
- }
- else { // must 64
- symtab64[symtabIdx].st_name = strtabsize;
- symtab64[symtabIdx].st_value = (*symbol)->value();
- symtab64[symtabIdx].st_size = getSymbolSize(**symbol);
- symtab64[symtabIdx].st_info = getSymbolInfo(**symbol);
- symtab64[symtabIdx].st_other = (*symbol)->visibility();
- symtab64[symtabIdx].st_shndx = getSymbolShndx(**symbol, pLayout);
- }
- // write out string
- strcpy((strtab + strtabsize), (*symbol)->name());
-
// sum up counters
++symtabIdx;
- strtabsize += (*symbol)->nameSize() + 1;
+ if (ResolveInfo::Section != (*symbol)->type())
+ strtabsize += (*symbol)->nameSize() + 1;
+ }
+
+ // emit symbols in TLS category, all symbols in TLS category shold be emitited
+ symEnd = symbols.tlsEnd();
+ for (symbol = symbols.tlsBegin(); symbol != symEnd; ++symbol) {
+ if (32 == bitclass())
+ emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+ symtabIdx);
+ else
+ emitSymbol64(symtab64[symtabIdx], **symbol, strtab, strtabsize,
+ symtabIdx);
+
+ // maintain output's symbol and index map
+ entry = m_pSymIndexMap->insert(*symbol, sym_exist);
+ entry->setValue(symtabIdx);
+ // sum up counters
+ ++symtabIdx;
+ if (ResolveInfo::Section != (*symbol)->type())
+ strtabsize += (*symbol)->nameSize() + 1;
+ }
+
+ // emit the reset of the symbols if the symbol is dynamic symbol
+ symEnd = pModule.sym_end();
+ for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
+ if (!isDynamicSymbol(**symbol))
+ continue;
+
+ if (32 == bitclass())
+ emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+ symtabIdx);
+ else
+ emitSymbol64(symtab64[symtabIdx], **symbol, strtab, strtabsize,
+ symtabIdx);
+
+ // maintain output's symbol and index map
+ entry = m_pSymIndexMap->insert(*symbol, sym_exist);
+ entry->setValue(symtabIdx);
+ // sum up counters
+ ++symtabIdx;
+ if (ResolveInfo::Section != (*symbol)->type())
+ strtabsize += (*symbol)->nameSize() + 1;
}
// emit DT_NEED
@@ -1005,39 +1162,40 @@
// 2. force count in --no-as-needed
// 3. judge --as-needed
ELFDynamic::iterator dt_need = dynamic().needBegin();
- InputTree::const_bfs_iterator input, inputEnd = pLDInfo.inputs().bfs_end();
- for (input = pLDInfo.inputs().bfs_begin(); input != inputEnd; ++input) {
- if (Input::DynObj == (*input)->type()) {
- // --add-needed
- if ((*input)->attribute()->isAddNeeded()) {
- // --no-as-needed
- if (!(*input)->attribute()->isAsNeeded()) {
- strcpy((strtab + strtabsize), (*input)->name().c_str());
- (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
- strtabsize += (*input)->name().size() + 1;
- ++dt_need;
- }
- // --as-needed
- else if ((*input)->isNeeded()) {
- strcpy((strtab + strtabsize), (*input)->name().c_str());
- (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
- strtabsize += (*input)->name().size() + 1;
- ++dt_need;
- }
+ Module::const_lib_iterator lib, libEnd = pModule.lib_end();
+ for (lib = pModule.lib_begin(); lib != libEnd; ++lib) {
+ // --add-needed
+ if ((*lib)->attribute()->isAddNeeded()) {
+ // --no-as-needed
+ if (!(*lib)->attribute()->isAsNeeded()) {
+ strcpy((strtab + strtabsize), (*lib)->name().c_str());
+ (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
+ strtabsize += (*lib)->name().size() + 1;
+ ++dt_need;
+ }
+ // --as-needed
+ else if ((*lib)->isNeeded()) {
+ strcpy((strtab + strtabsize), (*lib)->name().c_str());
+ (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
+ strtabsize += (*lib)->name().size() + 1;
+ ++dt_need;
}
}
- } // for
+ }
- // emit soname
// initialize value of ELF .dynamic section
- if (Output::DynObj == pOutput.type())
+ if (LinkerConfig::DynObj == config().codeGenType()) {
+ // set pointer to SONAME entry in dynamic string table.
dynamic().applySoname(strtabsize);
- dynamic().applyEntries(pLDInfo, *file_format);
+ }
+ dynamic().applyEntries(config(), *file_format);
dynamic().emit(dyn_sect, *dyn_region);
- strcpy((strtab + strtabsize), pOutput.name().c_str());
- strtabsize += pOutput.name().size() + 1;
-
+ // emit soname
+ if (LinkerConfig::DynObj == config().codeGenType()) {
+ strcpy((strtab + strtabsize), pModule.name().c_str());
+ strtabsize += pModule.name().size() + 1;
+ }
// emit hash table
// FIXME: this verion only emit SVR4 hash section.
// Please add GNU new hash section
@@ -1078,56 +1236,52 @@
}
/// sizeInterp - compute the size of the .interp section
-void GNULDBackend::sizeInterp(const Output& pOutput, const MCLDInfo& pLDInfo)
+void GNULDBackend::sizeInterp()
{
- assert(pOutput.type() == Output::Exec);
-
const char* dyld_name;
- if (pLDInfo.options().hasDyld())
- dyld_name = pLDInfo.options().dyld().c_str();
+ if (config().options().hasDyld())
+ dyld_name = config().options().dyld().c_str();
else
dyld_name = dyld();
- LDSection& interp = getExecFileFormat()->getInterp();
+ LDSection& interp = getOutputFormat()->getInterp();
interp.setSize(std::strlen(dyld_name) + 1);
}
/// emitInterp - emit the .interp
-void GNULDBackend::emitInterp(Output& pOutput, const MCLDInfo& pLDInfo)
+void GNULDBackend::emitInterp(MemoryArea& pOutput)
{
- assert(pOutput.type() == Output::Exec &&
- getExecFileFormat()->hasInterp() &&
- pOutput.hasMemArea());
+ if (getOutputFormat()->hasInterp()) {
+ const LDSection& interp = getOutputFormat()->getInterp();
+ MemoryRegion *region = pOutput.request(interp.offset(), interp.size());
+ const char* dyld_name;
+ if (config().options().hasDyld())
+ dyld_name = config().options().dyld().c_str();
+ else
+ dyld_name = dyld();
- const LDSection& interp = getExecFileFormat()->getInterp();
- MemoryRegion *region = pOutput.memArea()->request(
- interp.offset(), interp.size());
- const char* dyld_name;
- if (pLDInfo.options().hasDyld())
- dyld_name = pLDInfo.options().dyld().c_str();
- else
- dyld_name = dyld();
-
- std::memcpy(region->start(), dyld_name, interp.size());
+ std::memcpy(region->start(), dyld_name, interp.size());
+ }
}
/// getSectionOrder
-unsigned int GNULDBackend::getSectionOrder(const Output& pOutput,
- const LDSection& pSectHdr,
- const MCLDInfo& pInfo) const
+unsigned int GNULDBackend::getSectionOrder(const LDSection& pSectHdr) const
{
+ const ELFFileFormat* file_format = getOutputFormat();
+
// NULL section should be the "1st" section
if (LDFileFormat::Null == pSectHdr.kind())
return 0;
+ if (&pSectHdr == &file_format->getStrTab())
+ return SHO_STRTAB;
+
// if the section is not ALLOC, lay it out until the last possible moment
if (0 == (pSectHdr.flag() & llvm::ELF::SHF_ALLOC))
return SHO_UNDEFINED;
bool is_write = (pSectHdr.flag() & llvm::ELF::SHF_WRITE) != 0;
bool is_exec = (pSectHdr.flag() & llvm::ELF::SHF_EXECINSTR) != 0;
- const ELFFileFormat* file_format = getOutputFormat(pOutput);
-
// TODO: need to take care other possible output sections
switch (pSectHdr.kind()) {
case LDFileFormat::Regular:
@@ -1140,10 +1294,10 @@
} else if (!is_write) {
return SHO_RO;
} else {
- if (pInfo.options().hasRelro()) {
- if (pSectHdr.type() == llvm::ELF::SHT_PREINIT_ARRAY ||
- pSectHdr.type() == llvm::ELF::SHT_INIT_ARRAY ||
- pSectHdr.type() == llvm::ELF::SHT_FINI_ARRAY ||
+ if (config().options().hasRelro()) {
+ if (&pSectHdr == &file_format->getPreInitArray() ||
+ &pSectHdr == &file_format->getInitArray() ||
+ &pSectHdr == &file_format->getFiniArray() ||
&pSectHdr == &file_format->getCtors() ||
&pSectHdr == &file_format->getDtors() ||
&pSectHdr == &file_format->getJCR() ||
@@ -1152,17 +1306,22 @@
if (0 == pSectHdr.name().compare(".data.rel.ro.local"))
return SHO_RELRO_LOCAL;
}
+ if ((pSectHdr.flag() & llvm::ELF::SHF_TLS) != 0x0) {
+ return SHO_TLS_DATA;
+ }
return SHO_DATA;
}
case LDFileFormat::BSS:
+ if ((pSectHdr.flag() & llvm::ELF::SHF_TLS) != 0x0)
+ return SHO_TLS_BSS;
return SHO_BSS;
- case LDFileFormat::NamePool:
+ case LDFileFormat::NamePool: {
if (&pSectHdr == &file_format->getDynamic())
return SHO_RELRO;
return SHO_NAMEPOOL;
-
+ }
case LDFileFormat::Relocation:
if (&pSectHdr == &file_format->getRelPlt() ||
&pSectHdr == &file_format->getRelaPlt())
@@ -1171,7 +1330,7 @@
// get the order from target for target specific sections
case LDFileFormat::Target:
- return getTargetSectionOrder(pOutput, pSectHdr, pInfo);
+ return getTargetSectionOrder(pSectHdr);
// handle .interp
case LDFileFormat::Note:
@@ -1238,7 +1397,7 @@
/// getSymbolShndx - this function is called after layout()
uint64_t
-GNULDBackend::getSymbolShndx(const LDSymbol& pSymbol, const Layout& pLayout) const
+GNULDBackend::getSymbolShndx(const LDSymbol& pSymbol) const
{
if (pSymbol.resolveInfo()->isAbsolute())
return llvm::ELF::SHN_ABS;
@@ -1255,8 +1414,11 @@
}
}
+ if (pSymbol.resolveInfo()->isDefine() && !pSymbol.hasFragRef())
+ return llvm::ELF::SHN_ABS;
+
assert(pSymbol.hasFragRef() && "symbols must have fragment reference to get its index");
- return pLayout.getOutputLDSection(*pSymbol.fragRef()->frag())->index();
+ return pSymbol.fragRef()->frag()->getParent()->getSection().index();
}
/// getSymbolIdx - called by emitRelocation to get the ouput symbol table index
@@ -1267,12 +1429,12 @@
}
/// allocateCommonSymbols - allocate common symbols in the corresponding
-/// sections.
+/// sections. This is executed at pre-layout stage.
/// @refer Google gold linker: common.cc: 214
bool
-GNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
+GNULDBackend::allocateCommonSymbols(Module& pModule)
{
- SymbolCategory& symbol_list = pLinker.getOutputSymbols();
+ SymbolCategory& symbol_list = pModule.getSymbolTable();
if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
return true;
@@ -1282,27 +1444,27 @@
// FIXME: If the order of common symbols is defined, then sort common symbols
// std::sort(com_sym, com_end, some kind of order);
- // get or create corresponding BSS LDSection
- LDSection* bss_sect = &pLinker.getOrCreateOutputSectHdr(".bss",
- LDFileFormat::BSS,
- llvm::ELF::SHT_NOBITS,
- llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-
- LDSection* tbss_sect = &pLinker.getOrCreateOutputSectHdr(
- ".tbss",
- LDFileFormat::BSS,
- llvm::ELF::SHT_NOBITS,
- llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-
- assert(NULL != bss_sect && NULL !=tbss_sect);
+ // get corresponding BSS LDSection
+ ELFFileFormat* file_format = getOutputFormat();
+ LDSection& bss_sect = file_format->getBSS();
+ LDSection& tbss_sect = file_format->getTBSS();
// get or create corresponding BSS SectionData
- SectionData& bss_sect_data = pLinker.getOrCreateSectData(*bss_sect);
- SectionData& tbss_sect_data = pLinker.getOrCreateSectData(*tbss_sect);
+ SectionData* bss_sect_data = NULL;
+ if (bss_sect.hasSectionData())
+ bss_sect_data = bss_sect.getSectionData();
+ else
+ bss_sect_data = IRBuilder::CreateSectionData(bss_sect);
+
+ SectionData* tbss_sect_data = NULL;
+ if (tbss_sect.hasSectionData())
+ tbss_sect_data = tbss_sect.getSectionData();
+ else
+ tbss_sect_data = IRBuilder::CreateSectionData(tbss_sect);
// remember original BSS size
- uint64_t bss_offset = bss_sect->size();
- uint64_t tbss_offset = tbss_sect->size();
+ uint64_t bss_offset = bss_sect.size();
+ uint64_t tbss_offset = tbss_sect.size();
// allocate all local common symbols
com_end = symbol_list.localEnd();
@@ -1316,18 +1478,18 @@
// description here.
(*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
- (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
+ (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
// allocate TLS common symbol in tbss section
- tbss_offset += pLinker.getLayout().appendFragment(*frag,
- tbss_sect_data,
- (*com_sym)->value());
+ tbss_offset += ObjectBuilder::AppendFragment(*frag,
+ *tbss_sect_data,
+ (*com_sym)->value());
}
else {
- bss_offset += pLinker.getLayout().appendFragment(*frag,
- bss_sect_data,
- (*com_sym)->value());
+ bss_offset += ObjectBuilder::AppendFragment(*frag,
+ *bss_sect_data,
+ (*com_sym)->value());
}
}
}
@@ -1342,33 +1504,33 @@
// description here.
(*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
- (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
+ (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
// allocate TLS common symbol in tbss section
- tbss_offset += pLinker.getLayout().appendFragment(*frag,
- tbss_sect_data,
- (*com_sym)->value());
+ tbss_offset += ObjectBuilder::AppendFragment(*frag,
+ *tbss_sect_data,
+ (*com_sym)->value());
}
else {
- bss_offset += pLinker.getLayout().appendFragment(*frag,
- bss_sect_data,
- (*com_sym)->value());
+ bss_offset += ObjectBuilder::AppendFragment(*frag,
+ *bss_sect_data,
+ (*com_sym)->value());
}
}
- bss_sect->setSize(bss_offset);
- tbss_sect->setSize(tbss_offset);
+ bss_sect.setSize(bss_offset);
+ tbss_sect.setSize(tbss_offset);
symbol_list.changeCommonsToGlobal();
return true;
}
/// createProgramHdrs - base on output sections to create the program headers
-void GNULDBackend::createProgramHdrs(Output& pOutput, const MCLDInfo& pInfo)
+void GNULDBackend::createProgramHdrs(Module& pModule,
+ const FragmentLinker& pLinker)
{
- assert(pOutput.hasContext());
- ELFFileFormat *file_format = getOutputFormat(pOutput);
+ ELFFileFormat *file_format = getOutputFormat();
// make PT_PHDR
m_ELFSegmentTable.produce(llvm::ELF::PT_PHDR);
@@ -1379,75 +1541,57 @@
interp_seg->addSection(&file_format->getInterp());
}
- // FIXME: Should we consider -z relro here?
- if (pInfo.options().hasRelro()) {
- // if -z relro is given, we need to adjust sections' offset again, and let
- // PT_GNU_RELRO end on a common page boundary
- LDContext::SectionTable& sect_table = pOutput.context()->getSectionTable();
-
- size_t idx;
- for (idx = 0; idx < pOutput.context()->numOfSections(); ++idx) {
- // find the first non-relro section
- if (getSectionOrder(pOutput, *sect_table[idx], pInfo) > SHO_RELRO_LAST) {
- break;
- }
- }
-
- // align the first non-relro section to page boundary
- uint64_t offset = sect_table[idx]->offset();
- alignAddress(offset, commonPageSize(pInfo));
- sect_table[idx]->setOffset(offset);
-
- // set up remaining section's offset
- for (++idx; idx < pOutput.context()->numOfSections(); ++idx) {
- uint64_t offset;
- size_t prev_idx = idx - 1;
- if (LDFileFormat::BSS == sect_table[prev_idx]->kind())
- offset = sect_table[prev_idx]->offset();
- else
- offset = sect_table[prev_idx]->offset() + sect_table[prev_idx]->size();
-
- alignAddress(offset, sect_table[idx]->align());
- sect_table[idx]->setOffset(offset);
- }
- } // relro
-
- uint32_t cur_seg_flag, prev_seg_flag = getSegmentFlag(0);
- uint64_t padding = 0;
+ uint32_t cur_flag, prev_flag = getSegmentFlag(0);
ELFSegment* load_seg = NULL;
// make possible PT_LOAD segments
- LDContext::sect_iterator sect, sect_end = pOutput.context()->sectEnd();
- for (sect = pOutput.context()->sectBegin(); sect != sect_end; ++sect) {
+ Module::iterator sect, sect_end = pModule.end();
+ for (sect = pModule.begin(); sect != sect_end; ++sect) {
if (0 == ((*sect)->flag() & llvm::ELF::SHF_ALLOC) &&
LDFileFormat::Null != (*sect)->kind())
continue;
- // FIXME: Now only separate writable and non-writable PT_LOAD
- cur_seg_flag = getSegmentFlag((*sect)->flag());
- if ((prev_seg_flag & llvm::ELF::PF_W) ^ (cur_seg_flag & llvm::ELF::PF_W) ||
- LDFileFormat::Null == (*sect)->kind()) {
- // create new PT_LOAD segment
- load_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_LOAD);
- load_seg->setAlign(abiPageSize(pInfo));
+ cur_flag = getSegmentFlag((*sect)->flag());
+ bool createPT_LOAD = false;
+ if (LDFileFormat::Null == (*sect)->kind()) {
+ // 1. create text segment
+ createPT_LOAD = true;
+ }
+ else if (!config().options().omagic() &&
+ (prev_flag & llvm::ELF::PF_W) ^ (cur_flag & llvm::ELF::PF_W)) {
+ // 2. create data segment if w/o omagic set
+ createPT_LOAD = true;
+ }
+ else if ((*sect)->kind() == LDFileFormat::BSS &&
+ load_seg->isDataSegment() &&
+ config().scripts().addressMap().find(".bss") !=
+ (config().scripts().addressMap().end())) {
+ // 3. create bss segment if w/ -Tbss and there is a data segment
+ createPT_LOAD = true;
+ }
+ else {
+ if ((*sect != &(file_format->getText())) &&
+ (*sect != &(file_format->getData())) &&
+ (*sect != &(file_format->getBSS())) &&
+ (config().scripts().addressMap().find((*sect)->name()) !=
+ config().scripts().addressMap().end()))
+ // 4. create PT_LOAD for sections in address map except for text, data,
+ // and bss
+ createPT_LOAD = true;
+ }
- // check if this segment needs padding
- padding = 0;
- if (((*sect)->offset() & (abiPageSize(pInfo) - 1)) != 0)
- padding = abiPageSize(pInfo);
+ if (createPT_LOAD) {
+ // create new PT_LOAD segment
+ load_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_LOAD, cur_flag);
+ load_seg->setAlign(abiPageSize());
}
assert(NULL != load_seg);
load_seg->addSection((*sect));
- if (cur_seg_flag != prev_seg_flag)
- load_seg->updateFlag(cur_seg_flag);
+ if (cur_flag != prev_flag)
+ load_seg->updateFlag(cur_flag);
- if (LDFileFormat::Null != (*sect)->kind())
- (*sect)->setAddr(segmentStartAddr(pOutput, pInfo) +
- (*sect)->offset() +
- padding);
-
- prev_seg_flag = cur_seg_flag;
+ prev_flag = cur_flag;
}
// make PT_DYNAMIC
@@ -1458,16 +1602,22 @@
dyn_seg->addSection(&file_format->getDynamic());
}
- if (pInfo.options().hasRelro()) {
+ if (config().options().hasRelro()) {
// make PT_GNU_RELRO
ELFSegment* relro_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_RELRO);
- for (LDContext::sect_iterator sect = pOutput.context()->sectBegin();
- sect != pOutput.context()->sectEnd(); ++sect) {
- unsigned int order = getSectionOrder(pOutput, **sect, pInfo);
- if (SHO_RELRO_LOCAL == order ||
- SHO_RELRO == order ||
- SHO_RELRO_LAST == order) {
- relro_seg->addSection(*sect);
+ for (ELFSegmentFactory::iterator seg = elfSegmentTable().begin(),
+ segEnd = elfSegmentTable().end(); seg != segEnd; ++seg) {
+ if (llvm::ELF::PT_LOAD != (*seg).type())
+ continue;
+
+ for (ELFSegment::sect_iterator sect = (*seg).begin(),
+ sectEnd = (*seg).end(); sect != sectEnd; ++sect) {
+ unsigned int order = getSectionOrder(**sect);
+ if (SHO_RELRO_LOCAL == order ||
+ SHO_RELRO == order ||
+ SHO_RELRO_LAST == order) {
+ relro_seg->addSection(*sect);
+ }
}
}
}
@@ -1477,10 +1627,30 @@
ELFSegment* eh_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_EH_FRAME);
eh_seg->addSection(&file_format->getEhFrameHdr());
}
+
+ // make PT_TLS
+ if (file_format->hasTData() || file_format->hasTBSS()) {
+ ELFSegment* tls_seg = m_ELFSegmentTable.produce(llvm::ELF::PT_TLS);
+ if (file_format->hasTData())
+ tls_seg->addSection(&file_format->getTData());
+ if (file_format->hasTBSS())
+ tls_seg->addSection(&file_format->getTBSS());
+ }
+
+ // make PT_GNU_STACK
+ if (file_format->hasStackNote()) {
+ m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_STACK,
+ llvm::ELF::PF_R |
+ llvm::ELF::PF_W |
+ getSegmentFlag(file_format->getStackNote().flag()));
+ }
+
+ // create target dependent segments
+ doCreateProgramHdrs(pModule, pLinker);
}
/// setupProgramHdrs - set up the attributes of segments
-void GNULDBackend:: setupProgramHdrs(const Output& pOutput, const MCLDInfo& pInfo)
+void GNULDBackend::setupProgramHdrs(const FragmentLinker& pLinker)
{
// update segment info
ELFSegmentFactory::iterator seg, seg_end = m_ELFSegmentTable.end();
@@ -1499,7 +1669,7 @@
phdr_size = sizeof(llvm::ELF::Elf64_Phdr);
}
segment.setOffset(offset);
- segment.setVaddr(segmentStartAddr(pOutput, pInfo) + offset);
+ segment.setVaddr(segmentStartAddr(pLinker) + offset);
segment.setPaddr(segment.vaddr());
segment.setFilesz(numOfSegments() * phdr_size);
segment.setMemsz(numOfSegments() * phdr_size);
@@ -1511,15 +1681,15 @@
if (segment.numOfSections() == 0)
continue;
- segment.setOffset(segment.getFirstSection()->offset());
+ segment.setOffset(segment.front()->offset());
if (llvm::ELF::PT_LOAD == segment.type() &&
- LDFileFormat::Null == segment.getFirstSection()->kind())
- segment.setVaddr(segmentStartAddr(pOutput, pInfo));
+ LDFileFormat::Null == segment.front()->kind())
+ segment.setVaddr(segmentStartAddr(pLinker));
else
- segment.setVaddr(segment.getFirstSection()->addr());
+ segment.setVaddr(segment.front()->addr());
segment.setPaddr(segment.vaddr());
- const LDSection* last_sect = segment.getLastSection();
+ const LDSection* last_sect = segment.back();
assert(NULL != last_sect);
uint64_t file_size = last_sect->offset() - segment.offset();
if (LDFileFormat::BSS != last_sect->kind())
@@ -1530,33 +1700,32 @@
}
}
-/// createGNUStackInfo - create an output GNU stack section or segment if needed
+/// setupGNUStackInfo - setup the section flag of .note.GNU-stack in output
/// @ref gold linker: layout.cc:2608
-void GNULDBackend::createGNUStackInfo(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker)
+void GNULDBackend::setupGNUStackInfo(Module& pModule, FragmentLinker& pLinker)
{
uint32_t flag = 0x0;
- if (pInfo.options().hasStackSet()) {
+ if (config().options().hasStackSet()) {
// 1. check the command line option (-z execstack or -z noexecstack)
- if (pInfo.options().hasExecStack())
+ if (config().options().hasExecStack())
flag = llvm::ELF::SHF_EXECINSTR;
- } else {
+ }
+ else {
// 2. check the stack info from the input objects
+ // FIXME: since we alway emit .note.GNU-stack in output now, we may be able
+ // to check this from the output .note.GNU-stack directly after section
+ // merging is done
size_t object_count = 0, stack_note_count = 0;
- mcld::InputTree::const_bfs_iterator input, inEnd = pInfo.inputs().bfs_end();
- for (input=pInfo.inputs().bfs_begin(); input!=inEnd; ++input) {
- if ((*input)->type() == Input::Object) {
- ++object_count;
- const LDSection* sect = (*input)->context()->getSection(
- ".note.GNU-stack");
- if (NULL != sect) {
- ++stack_note_count;
- // 2.1 found a stack note that is set as executable
- if (0 != (llvm::ELF::SHF_EXECINSTR & sect->flag())) {
- flag = llvm::ELF::SHF_EXECINSTR;
- break;
- }
+ Module::const_obj_iterator obj, objEnd = pModule.obj_end();
+ for (obj = pModule.obj_begin(); obj != objEnd; ++obj) {
+ ++object_count;
+ const LDSection* sect = (*obj)->context()->getSection(".note.GNU-stack");
+ if (NULL != sect) {
+ ++stack_note_count;
+ // 2.1 found a stack note that is set as executable
+ if (0 != (llvm::ELF::SHF_EXECINSTR & sect->flag())) {
+ flag = llvm::ELF::SHF_EXECINSTR;
+ break;
}
}
}
@@ -1572,69 +1741,294 @@
flag = llvm::ELF::SHF_EXECINSTR;
}
- if (pOutput.type() != Output::Object)
- m_ELFSegmentTable.produce(llvm::ELF::PT_GNU_STACK,
- llvm::ELF::PF_R |
- llvm::ELF::PF_W |
- getSegmentFlag(flag));
+ if (getOutputFormat()->hasStackNote()) {
+ getOutputFormat()->getStackNote().setFlag(flag);
+ }
+}
+
+/// setupRelro - setup the offset constraint of PT_RELRO
+void GNULDBackend::setupRelro(Module& pModule)
+{
+ assert(config().options().hasRelro());
+ // if -z relro is given, we need to adjust sections' offset again, and let
+ // PT_GNU_RELRO end on a common page boundary
+
+ Module::iterator sect = pModule.begin();
+ for (Module::iterator sect_end = pModule.end(); sect != sect_end; ++sect) {
+ // find the first non-relro section
+ if (getSectionOrder(**sect) > SHO_RELRO_LAST)
+ break;
+ }
+
+ // align the first non-relro section to page boundary
+ uint64_t offset = (*sect)->offset();
+ alignAddress(offset, commonPageSize());
+ (*sect)->setOffset(offset);
+
+ // It seems that compiler think .got and .got.plt are continuous (w/o any
+ // padding between). If .got is the last section in PT_RELRO and it's not
+ // continuous to its next section (i.e. .got.plt), we need to add padding
+ // in front of .got instead.
+ // FIXME: Maybe we can handle this in a more general way.
+ LDSection& got = getOutputFormat()->getGOT();
+ if ((getSectionOrder(got) == SHO_RELRO_LAST) &&
+ (got.offset() + got.size() != offset)) {
+ got.setOffset(offset - got.size());
+ }
+
+ // set up remaining section's offset
+ setOutputSectionOffset(pModule, ++sect, pModule.end());
+}
+
+/// setOutputSectionOffset - helper function to set a group of output sections'
+/// offset, and set pSectBegin to pStartOffset if pStartOffset is not -1U.
+void GNULDBackend::setOutputSectionOffset(Module& pModule,
+ Module::iterator pSectBegin,
+ Module::iterator pSectEnd,
+ uint64_t pStartOffset)
+{
+ if (pSectBegin == pModule.end())
+ return;
+
+ assert(pSectEnd == pModule.end() ||
+ (pSectEnd != pModule.end() &&
+ (*pSectBegin)->index() <= (*pSectEnd)->index()));
+
+ if (pStartOffset != -1U) {
+ (*pSectBegin)->setOffset(pStartOffset);
+ ++pSectBegin;
+ }
+
+ // set up the "cur" and "prev" iterator
+ Module::iterator cur = pSectBegin;
+ Module::iterator prev = pSectBegin;
+ if (cur != pModule.begin())
+ --prev;
else
- pLinker.getOrCreateOutputSectHdr(".note.GNU-stack",
- LDFileFormat::Note,
- llvm::ELF::SHT_PROGBITS,
- flag);
+ ++cur;
+
+ for (; cur != pSectEnd; ++cur, ++prev) {
+ uint64_t offset = 0x0;
+ switch ((*prev)->kind()) {
+ case LDFileFormat::Null:
+ offset = sectionStartOffset();
+ break;
+ case LDFileFormat::BSS:
+ offset = (*prev)->offset();
+ break;
+ default:
+ offset = (*prev)->offset() + (*prev)->size();
+ break;
+ }
+
+ alignAddress(offset, (*cur)->align());
+ (*cur)->setOffset(offset);
+ }
+}
+
+/// setOutputSectionOffset - helper function to set output sections' address
+void GNULDBackend::setOutputSectionAddress(FragmentLinker& pLinker,
+ Module& pModule,
+ Module::iterator pSectBegin,
+ Module::iterator pSectEnd)
+{
+ if (pSectBegin == pModule.end())
+ return;
+
+ assert(pSectEnd == pModule.end() ||
+ (pSectEnd != pModule.end() &&
+ (*pSectBegin)->index() <= (*pSectEnd)->index()));
+
+ for (ELFSegmentFactory::iterator seg = elfSegmentTable().begin(),
+ segEnd = elfSegmentTable().end(), prev = elfSegmentTable().end();
+ seg != segEnd; prev = seg, ++seg) {
+ if (llvm::ELF::PT_LOAD != (*seg).type())
+ continue;
+
+ uint64_t start_addr = 0x0;
+ ScriptOptions::AddressMap::const_iterator mapping;
+ if ((*seg).front()->kind() == LDFileFormat::Null)
+ mapping = config().scripts().addressMap().find(".text");
+ else if ((*seg).isDataSegment())
+ mapping = config().scripts().addressMap().find(".data");
+ else if ((*seg).isBssSegment())
+ mapping = config().scripts().addressMap().find(".bss");
+ else
+ mapping = config().scripts().addressMap().find((*seg).front()->name());
+
+ if (mapping != config().scripts().addressMap().end()) {
+ // check address mapping
+ start_addr = mapping.getEntry()->value();
+ const uint64_t remainder = start_addr % abiPageSize();
+ if (remainder != (*seg).front()->offset() % abiPageSize()) {
+ uint64_t padding = abiPageSize() + remainder -
+ (*seg).front()->offset() % abiPageSize();
+ setOutputSectionOffset(pModule,
+ pModule.begin() + (*seg).front()->index(),
+ pModule.end(),
+ (*seg).front()->offset() + padding);
+ if (config().options().hasRelro())
+ setupRelro(pModule);
+ }
+ }
+ else {
+ if ((*seg).front()->kind() == LDFileFormat::Null) {
+ // 1st PT_LOAD
+ start_addr = segmentStartAddr(pLinker);
+ }
+ else if ((*prev).front()->kind() == LDFileFormat::Null) {
+ // prev segment is 1st PT_LOAD
+ start_addr = segmentStartAddr(pLinker) + (*seg).front()->offset();
+ }
+ else {
+ // Others
+ start_addr = (*prev).front()->addr() + (*seg).front()->offset();
+ }
+
+ // padding
+ if (((*seg).front()->offset() & (abiPageSize() - 1)) != 0)
+ start_addr += abiPageSize();
+ }
+
+ for (ELFSegment::sect_iterator sect = (*seg).begin(),
+ sectEnd = (*seg).end(); sect != sectEnd; ++sect) {
+ if ((*sect)->index() < (*pSectBegin)->index())
+ continue;
+
+ if (LDFileFormat::Null == (*sect)->kind())
+ continue;
+
+ if (sect == pSectEnd)
+ return;
+
+ if (sect != (*seg).begin())
+ (*sect)->setAddr(start_addr + (*sect)->offset() -
+ (*seg).front()->offset());
+ else
+ (*sect)->setAddr(start_addr);
+ }
+ }
}
/// preLayout - Backend can do any needed modification before layout
-void GNULDBackend::preLayout(const Output& pOutput,
- const MCLDInfo& pLDInfo,
- MCLinker& pLinker)
+void GNULDBackend::preLayout(Module& pModule, FragmentLinker& pLinker)
{
// prelayout target first
- doPreLayout(pOutput, pLDInfo, pLinker);
+ doPreLayout(pLinker);
- if (pLDInfo.options().hasEhFrameHdr()) {
+ if (config().options().hasEhFrameHdr() && getOutputFormat()->hasEhFrame()) {
// init EhFrameHdr and size the output section
- ELFFileFormat* format = getOutputFormat(pOutput);
- assert(NULL != getEhFrame());
- m_pEhFrameHdr = new EhFrameHdr(*getEhFrame(),
- format->getEhFrame(),
- format->getEhFrameHdr());
+ ELFFileFormat* format = getOutputFormat();
+ m_pEhFrameHdr = new EhFrameHdr(format->getEhFrameHdr(),
+ format->getEhFrame());
m_pEhFrameHdr->sizeOutput();
}
+
+ // change .tbss and .tdata section symbol from Local to TLS category
+ if (NULL != f_pTDATA)
+ pModule.getSymbolTable().changeLocalToTLS(*f_pTDATA);
+
+ if (NULL != f_pTBSS)
+ pModule.getSymbolTable().changeLocalToTLS(*f_pTBSS);
+
+ // To merge input's relocation sections into output's relocation sections.
+ //
+ // If we are generating relocatables (-r), move input relocation sections
+ // to corresponding output relocation sections.
+ if (LinkerConfig::Object == config().codeGenType()) {
+ Module::obj_iterator input, inEnd = pModule.obj_end();
+ for (input = pModule.obj_begin(); input != inEnd; ++input) {
+ LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
+ for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
+
+ // get the output relocation LDSection with identical name.
+ LDSection* output_sect = pModule.getSection((*rs)->name());
+ if (NULL == output_sect) {
+ output_sect = LDSection::Create((*rs)->name(),
+ (*rs)->kind(),
+ (*rs)->type(),
+ (*rs)->flag());
+
+ output_sect->setAlign((*rs)->align());
+ pModule.getSectionTable().push_back(output_sect);
+ }
+
+ // set output relocation section link
+ const LDSection* input_link = (*rs)->getLink();
+ assert(NULL != input_link && "Illegal input relocation section.");
+
+ // get the linked output section
+ LDSection* output_link = pModule.getSection(input_link->name());
+ assert(NULL != output_link);
+
+ output_sect->setLink(output_link);
+
+ // get output relcoationData, create one if not exist
+ if (!output_sect->hasRelocData())
+ IRBuilder::CreateRelocData(*output_sect);
+
+ RelocData* out_reloc_data = output_sect->getRelocData();
+
+ // move relocations from input's to output's RelcoationData
+ RelocData::FragmentListType& out_list =
+ out_reloc_data->getFragmentList();
+ RelocData::FragmentListType& in_list =
+ (*rs)->getRelocData()->getFragmentList();
+ out_list.splice(out_list.end(), in_list);
+
+ // size output
+ if (llvm::ELF::SHT_REL == output_sect->type())
+ output_sect->setSize(out_reloc_data->size() * getRelEntrySize());
+ else if (llvm::ELF::SHT_RELA == output_sect->type())
+ output_sect->setSize(out_reloc_data->size() * getRelaEntrySize());
+ else {
+ fatal(diag::unknown_reloc_section_type) << output_sect->type()
+ << output_sect->name();
+ }
+ } // end of for each relocation section
+ } // end of for each input
+ } // end of if
+
+ // set up the section flag of .note.GNU-stack section
+ setupGNUStackInfo(pModule, pLinker);
}
/// postLayout - Backend can do any needed modification after layout
-void GNULDBackend::postLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker)
+void GNULDBackend::postLayout(Module& pModule,
+ FragmentLinker& pLinker)
{
// 1. emit program headers
- if (pOutput.type() != Output::Object) {
+ if (LinkerConfig::Object != config().codeGenType()) {
// 1.1 create program headers
- createProgramHdrs(pLinker.getLDInfo().output(), pInfo);
+ createProgramHdrs(pModule, pLinker);
}
- // 1.2 create special GNU Stack note section or segment
- createGNUStackInfo(pOutput, pInfo, pLinker);
+ if (LinkerConfig::Object != config().codeGenType()) {
+ if (config().options().hasRelro()) {
+ // 1.2 set up the offset constraint of PT_RELRO
+ setupRelro(pModule);
+ }
- if (pOutput.type() != Output::Object) {
- // 1.3 set up the attributes of program headers
- setupProgramHdrs(pOutput, pInfo);
+ // 1.3 set up the output sections' address
+ setOutputSectionAddress(pLinker, pModule, pModule.begin(), pModule.end());
+
+ // 1.4 do relaxation
+ relax(pModule, pLinker);
+
+ // 1.5 set up the attributes of program headers
+ setupProgramHdrs(pLinker);
}
// 2. target specific post layout
- doPostLayout(pOutput, pInfo, pLinker);
+ doPostLayout(pModule, pLinker);
}
-void GNULDBackend::postProcessing(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker)
+void GNULDBackend::postProcessing(FragmentLinker& pLinker, MemoryArea& pOutput)
{
- if (pInfo.options().hasEhFrameHdr()) {
+ if (config().options().hasEhFrameHdr() && getOutputFormat()->hasEhFrame()) {
// emit eh_frame_hdr
if (bitclass() == 32)
- m_pEhFrameHdr->emitOutput<32>(pLinker.getLDInfo().output(),
- pLinker);
+ m_pEhFrameHdr->emitOutput<32>(pOutput);
}
}
@@ -1666,8 +2060,7 @@
/// isDynamicSymbol
/// @ref Google gold linker: symtab.cc:311
-bool GNULDBackend::isDynamicSymbol(const LDSymbol& pSymbol,
- const Output& pOutput)
+bool GNULDBackend::isDynamicSymbol(const LDSymbol& pSymbol)
{
// If a local symbol is in the LDContext's symbol table, it's a real local
// symbol. We should not add it
@@ -1676,78 +2069,123 @@
// If we are building shared object, and the visibility is external, we
// need to add it.
- if (Output::DynObj == pOutput.type() || Output::Exec == pOutput.type())
+ if (LinkerConfig::DynObj == config().codeGenType() ||
+ LinkerConfig::Exec == config().codeGenType()) {
if (pSymbol.resolveInfo()->visibility() == ResolveInfo::Default ||
- pSymbol.resolveInfo()->visibility() == ResolveInfo::Protected)
+ pSymbol.resolveInfo()->visibility() == ResolveInfo::Protected) {
return true;
+ }
+ }
+ return false;
+}
+
+/// isDynamicSymbol
+/// @ref Google gold linker: symtab.cc:311
+bool GNULDBackend::isDynamicSymbol(const ResolveInfo& pResolveInfo)
+{
+ // If a local symbol is in the LDContext's symbol table, it's a real local
+ // symbol. We should not add it
+ if (pResolveInfo.binding() == ResolveInfo::Local)
+ return false;
+
+ // If we are building shared object, and the visibility is external, we
+ // need to add it.
+ if (LinkerConfig::DynObj == config().codeGenType() ||
+ LinkerConfig::Exec == config().codeGenType()) {
+ if (pResolveInfo.visibility() == ResolveInfo::Default ||
+ pResolveInfo.visibility() == ResolveInfo::Protected) {
+ return true;
+ }
+ }
return false;
}
/// commonPageSize - the common page size of the target machine.
/// @ref gold linker: target.h:135
-uint64_t GNULDBackend::commonPageSize(const MCLDInfo& pInfo) const
+uint64_t GNULDBackend::commonPageSize() const
{
- if (pInfo.options().commPageSize() > 0)
- return std::min(pInfo.options().commPageSize(), abiPageSize(pInfo));
+ if (config().options().commPageSize() > 0)
+ return std::min(config().options().commPageSize(), abiPageSize());
else
- return std::min(static_cast<uint64_t>(0x1000), abiPageSize(pInfo));
+ return std::min(static_cast<uint64_t>(0x1000), abiPageSize());
}
/// abiPageSize - the abi page size of the target machine.
/// @ref gold linker: target.h:125
-uint64_t GNULDBackend::abiPageSize(const MCLDInfo& pInfo) const
+uint64_t GNULDBackend::abiPageSize() const
{
- if (pInfo.options().maxPageSize() > 0)
- return pInfo.options().maxPageSize();
+ if (config().options().maxPageSize() > 0)
+ return config().options().maxPageSize();
else
return static_cast<uint64_t>(0x1000);
}
-/// isOutputPIC - return whether the output is position-independent
-bool GNULDBackend::isOutputPIC(const Output& pOutput,
- const MCLDInfo& pInfo) const
-{
- if (Output::DynObj == pOutput.type() || pInfo.options().isPIE())
- return true;
- return false;
-}
-
-/// isStaticLink - return whether we're doing static link
-bool GNULDBackend::isStaticLink(const Output& pOutput,
- const MCLDInfo& pInfo) const
-{
- InputTree::const_iterator it = pInfo.inputs().begin();
- if (!isOutputPIC(pOutput, pInfo) && (*it)->attribute()->isStatic())
- return true;
- return false;
-}
-
/// isSymbolPreemtible - whether the symbol can be preemted by other
/// link unit
/// @ref Google gold linker, symtab.h:551
-bool GNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym,
- const MCLDInfo& pLDInfo,
- const Output& pOutput) const
+bool GNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym) const
{
if (pSym.other() != ResolveInfo::Default)
return false;
- if (Output::DynObj != pOutput.type())
+ // This is because the codeGenType of pie is DynObj. And gold linker check
+ // the "shared" option instead.
+ if (config().options().isPIE())
return false;
- if (pLDInfo.options().Bsymbolic())
+ if (LinkerConfig::DynObj != config().codeGenType())
+ return false;
+
+ if (config().options().Bsymbolic())
+ return false;
+
+ // A local defined symbol should be non-preemptible.
+ // This issue is found when linking libstdc++ on freebsd. A R_386_GOT32
+ // relocation refers to a local defined symbol, and we should generate a
+ // relative dynamic relocation when applying the relocation.
+ if (pSym.isDefine() && pSym.binding() == ResolveInfo::Local)
return false;
return true;
}
+/// symbolNeedsDynRel - return whether the symbol needs a dynamic relocation
+/// @ref Google gold linker, symtab.h:645
+bool GNULDBackend::symbolNeedsDynRel(const FragmentLinker& pLinker,
+ const ResolveInfo& pSym,
+ bool pSymHasPLT,
+ bool isAbsReloc) const
+{
+ // an undefined reference in the executables should be statically
+ // resolved to 0 and no need a dynamic relocation
+ if (pSym.isUndef() &&
+ !pSym.isDyn() &&
+ LinkerConfig::Exec == config().codeGenType())
+ return false;
+
+ if (pSym.isAbsolute())
+ return false;
+ if (pLinker.isOutputPIC() && isAbsReloc)
+ return true;
+ if (pSymHasPLT && ResolveInfo::Function == pSym.type())
+ return false;
+ if (!pLinker.isOutputPIC() && pSymHasPLT)
+ return false;
+ if (pSym.isDyn() || pSym.isUndef() ||
+ isSymbolPreemptible(pSym))
+ return true;
+
+ return false;
+}
+
/// symbolNeedsPLT - return whether the symbol needs a PLT entry
/// @ref Google gold linker, symtab.h:596
-bool GNULDBackend::symbolNeedsPLT(const ResolveInfo& pSym,
- const MCLDInfo& pLDInfo,
- const Output& pOutput) const
+bool GNULDBackend::symbolNeedsPLT(const FragmentLinker& pLinker,
+ const ResolveInfo& pSym) const
{
- if (pSym.isUndef() && !pSym.isDyn() && pOutput.type() != Output::DynObj)
+ if (pSym.isUndef() &&
+ !pSym.isDyn() &&
+ LinkerConfig::DynObj != config().codeGenType())
return false;
// An IndirectFunc symbol (i.e., STT_GNU_IFUNC) always needs a plt entry
@@ -1757,66 +2195,148 @@
if (pSym.type() != ResolveInfo::Function)
return false;
- if (isStaticLink(pOutput, pLDInfo) || pLDInfo.options().isPIE())
+ if (pLinker.isStaticLink() && !pLinker.isOutputPIC())
+ return false;
+
+ if (config().options().isPIE())
return false;
return (pSym.isDyn() ||
pSym.isUndef() ||
- isSymbolPreemptible(pSym, pLDInfo, pOutput));
+ isSymbolPreemptible(pSym));
}
-/// symbolNeedsDynRel - return whether the symbol needs a dynamic relocation
-/// @ref Google gold linker, symtab.h:645
-bool GNULDBackend::symbolNeedsDynRel(const ResolveInfo& pSym,
- bool pSymHasPLT,
- const MCLDInfo& pLDInfo,
- const Output& pOutput,
- bool isAbsReloc) const
+/// symbolHasFinalValue - return true if the symbol's value can be decided at
+/// link time
+/// @ref Google gold linker, Symbol::final_value_is_known
+bool GNULDBackend::symbolFinalValueIsKnown(const FragmentLinker& pLinker,
+ const ResolveInfo& pSym) const
{
- // an undefined reference in the executables should be statically
- // resolved to 0 and no need a dynamic relocation
- if (pSym.isUndef() && !pSym.isDyn() && (Output::Exec == pOutput.type()))
+ // if the output is pic code or if not executables, symbols' value may change
+ // at runtime
+ if (pLinker.isOutputPIC() || LinkerConfig::Exec != config().codeGenType())
return false;
- if (pSym.isAbsolute())
+
+ // if the symbol is from dynamic object, then its value is unknown
+ if (pSym.isDyn())
return false;
- if (isOutputPIC(pOutput, pLDInfo) && isAbsReloc)
- return true;
- if (pSymHasPLT && ResolveInfo::Function == pSym.type())
- return false;
- if (!isOutputPIC(pOutput, pLDInfo) && pSymHasPLT)
- return false;
- if (pSym.isDyn() || pSym.isUndef() ||
- isSymbolPreemptible(pSym, pLDInfo, pOutput))
+
+ // if the symbol is not in dynamic object and is not undefined, then its value
+ // is known
+ if (!pSym.isUndef())
return true;
- return false;
+ // if the symbol is undefined and not in dynamic objects, for example, a weak
+ // undefined symbol, then whether the symbol's final value can be known
+ // depends on whrther we're doing static link
+ return pLinker.isStaticLink();
}
/// symbolNeedsCopyReloc - return whether the symbol needs a copy relocation
-bool GNULDBackend::symbolNeedsCopyReloc(const Layout& pLayout,
+bool GNULDBackend::symbolNeedsCopyReloc(const FragmentLinker& pLinker,
const Relocation& pReloc,
- const ResolveInfo& pSym,
- const MCLDInfo& pLDInfo,
- const Output& pOutput) const
+ const ResolveInfo& pSym) const
{
// only the reference from dynamic executable to non-function symbol in
// the dynamic objects may need copy relocation
- if (isOutputPIC(pOutput, pLDInfo) ||
+ if (pLinker.isOutputPIC() ||
!pSym.isDyn() ||
pSym.type() == ResolveInfo::Function ||
pSym.size() == 0)
return false;
// check if the option -z nocopyreloc is given
- if (pLDInfo.options().hasNoCopyReloc())
+ if (config().options().hasNoCopyReloc())
return false;
// TODO: Is this check necessary?
// if relocation target place is readonly, a copy relocation is needed
- if ((pLayout.getOutputLDSection(*pReloc.targetRef().frag())->flag() &
- llvm::ELF::SHF_WRITE) == 0)
+ uint32_t flag = pReloc.targetRef().frag()->getParent()->getSection().flag();
+ if (0 == (flag & llvm::ELF::SHF_WRITE))
return true;
return false;
}
+LDSymbol& GNULDBackend::getTDATASymbol()
+{
+ assert(NULL != f_pTDATA);
+ return *f_pTDATA;
+}
+
+const LDSymbol& GNULDBackend::getTDATASymbol() const
+{
+ assert(NULL != f_pTDATA);
+ return *f_pTDATA;
+}
+
+LDSymbol& GNULDBackend::getTBSSSymbol()
+{
+ assert(NULL != f_pTBSS);
+ return *f_pTBSS;
+}
+
+const LDSymbol& GNULDBackend::getTBSSSymbol() const
+{
+ assert(NULL != f_pTBSS);
+ return *f_pTBSS;
+}
+
+void GNULDBackend::checkAndSetHasTextRel(const LDSection& pSection)
+{
+ if (m_bHasTextRel)
+ return;
+
+ // if the target section of the dynamic relocation is ALLOCATE but is not
+ // writable, than we should set DF_TEXTREL
+ const uint32_t flag = pSection.flag();
+ if (0 == (flag & llvm::ELF::SHF_WRITE) && (flag & llvm::ELF::SHF_ALLOC))
+ m_bHasTextRel = true;
+
+ return;
+}
+
+/// initBRIslandFactory - initialize the branch island factory for relaxation
+bool GNULDBackend::initBRIslandFactory()
+{
+ if (NULL == m_pBRIslandFactory) {
+ m_pBRIslandFactory = new BranchIslandFactory(maxBranchOffset());
+ }
+ return true;
+}
+
+/// initStubFactory - initialize the stub factory for relaxation
+bool GNULDBackend::initStubFactory()
+{
+ if (NULL == m_pStubFactory) {
+ m_pStubFactory = new StubFactory();
+ }
+ return true;
+}
+
+bool GNULDBackend::relax(Module& pModule, FragmentLinker& pLinker)
+{
+ if (!mayRelax())
+ return true;
+
+ bool finished = true;
+ do {
+ if (doRelax(pModule, pLinker, finished)) {
+ // If the sections (e.g., .text) are relaxed, the layout is also changed
+ // We need to do the following:
+
+ // 1. set up the offset
+ setOutputSectionOffset(pModule, pModule.begin(), pModule.end());
+
+ // 2. set up the offset constraint of PT_RELRO
+ if (config().options().hasRelro())
+ setupRelro(pModule);
+
+ // 3. set up the output sections' address
+ setOutputSectionAddress(pLinker, pModule, pModule.begin(), pModule.end());
+ }
+ } while (!finished);
+
+ return true;
+}
+
diff --git a/lib/Target/GOT.cpp b/lib/Target/GOT.cpp
index f9e7b91..32afdff 100644
--- a/lib/Target/GOT.cpp
+++ b/lib/Target/GOT.cpp
@@ -6,8 +6,12 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+#include <llvm/Support/Casting.h>
+#include <mcld/LD/LDSection.h>
#include <mcld/Target/GOT.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/IRBuilder.h>
#include <cstring>
#include <cstdlib>
@@ -15,26 +19,26 @@
using namespace mcld;
//===----------------------------------------------------------------------===//
-// GOTEntry
+// GOT::Entry
//===----------------------------------------------------------------------===//
-GOTEntry::GOTEntry(uint64_t pContent, size_t pEntrySize, SectionData* pParent)
+GOT::Entry::Entry(uint64_t pContent, size_t pEntrySize, SectionData* pParent)
: TargetFragment(Fragment::Target, pParent),
- f_Content(pContent), m_EntrySize(pEntrySize) {
+ f_Content(pContent),
+ m_EntrySize(pEntrySize) {
}
-GOTEntry::~GOTEntry()
+GOT::Entry::~Entry()
{
}
//===----------------------------------------------------------------------===//
// GOT
//===----------------------------------------------------------------------===//
-GOT::GOT(LDSection& pSection,
- SectionData& pSectionData,
- size_t pEntrySize)
+GOT::GOT(LDSection& pSection, size_t pEntrySize)
: m_Section(pSection),
- m_SectionData(pSectionData),
- f_EntrySize(pEntrySize) {
+ f_EntrySize(pEntrySize),
+ m_pLast(NULL) {
+ m_SectionData = IRBuilder::CreateSectionData(pSection);
}
GOT::~GOT()
@@ -46,3 +50,34 @@
return f_EntrySize;
}
+void GOT::reserve(size_t pNum)
+{
+ for (size_t i = 0; i < pNum; i++) {
+ new Entry(0, f_EntrySize, m_SectionData);
+ }
+}
+
+GOT::Entry* GOT::consume()
+{
+ if (NULL == m_pLast) {
+ assert(!empty() && "Consume empty GOT entry!");
+ m_pLast = llvm::cast<Entry>(&m_SectionData->front());
+ return m_pLast;
+ }
+
+ m_pLast = llvm::cast<Entry>(m_pLast->getNextNode());
+ return m_pLast;
+}
+
+void GOT::finalizeSectionSize()
+{
+ m_Section.setSize(m_SectionData->size() * f_EntrySize);
+
+ uint32_t offset = 0;
+ SectionData::iterator frag, fragEnd = m_SectionData->end();
+ for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) {
+ frag->setOffset(offset);
+ offset += frag->size();
+ }
+}
+
diff --git a/lib/Target/Mips/Android.mk b/lib/Target/Mips/Android.mk
index 4707c4b..dd3905d 100644
--- a/lib/Target/Mips/Android.mk
+++ b/lib/Target/Mips/Android.mk
@@ -3,11 +3,12 @@
mcld_mips_target_SRC_FILES := \
MipsDiagnostic.cpp \
MipsELFDynamic.cpp \
- MipsELFSectLinker.cpp \
+ MipsELFMCLinker.cpp \
+ MipsEmulation.cpp \
MipsGOT.cpp \
MipsLDBackend.cpp \
+ MipsMCLinker.cpp \
MipsRelocationFactory.cpp \
- MipsSectLinker.cpp \
MipsTargetMachine.cpp
# For the host
diff --git a/lib/Target/Mips/MipsDiagnostic.cpp b/lib/Target/Mips/MipsDiagnostic.cpp
index f6b6339..2d5b7d9 100644
--- a/lib/Target/Mips/MipsDiagnostic.cpp
+++ b/lib/Target/Mips/MipsDiagnostic.cpp
@@ -28,7 +28,7 @@
//==========================
// InitializeMipsDiagnostic
-extern "C" void LLVMInitializeMipsDiagnosticLineInfo() {
+extern "C" void MCLDInitializeMipsDiagnosticLineInfo() {
// Register the linker frontend
mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheMipselTarget, createMipsDiagLineInfo);
}
diff --git a/lib/Target/Mips/MipsELFDynamic.cpp b/lib/Target/Mips/MipsELFDynamic.cpp
index cd692ac..fd779f3 100644
--- a/lib/Target/Mips/MipsELFDynamic.cpp
+++ b/lib/Target/Mips/MipsELFDynamic.cpp
@@ -21,7 +21,7 @@
MIPS_BASE_ADDRESS = 0x70000006,
MIPS_LOCAL_GOTNO = 0x7000000a,
MIPS_SYMTABNO = 0x70000011,
- MIPS_GOTSYM = 0x70000013,
+ MIPS_GOTSYM = 0x70000013
};
MipsELFDynamic::MipsELFDynamic(const MipsGNULDBackend& pParent)
diff --git a/lib/Target/Mips/MipsELFMCLinker.cpp b/lib/Target/Mips/MipsELFMCLinker.cpp
new file mode 100644
index 0000000..3964ee8
--- /dev/null
+++ b/lib/Target/Mips/MipsELFMCLinker.cpp
@@ -0,0 +1,23 @@
+//===- MipsELFMCLinker.cpp ------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "MipsELFMCLinker.h"
+#include <mcld/LinkerConfig.h>
+
+using namespace mcld;
+
+MipsELFMCLinker::MipsELFMCLinker(LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ MemoryArea& pOutput)
+ : ELFMCLinker(pConfig, pModule, pOutput) {
+}
+
+MipsELFMCLinker::~MipsELFMCLinker()
+{
+}
+
diff --git a/lib/Target/Mips/MipsELFMCLinker.h b/lib/Target/Mips/MipsELFMCLinker.h
new file mode 100644
index 0000000..2c240ad
--- /dev/null
+++ b/lib/Target/Mips/MipsELFMCLinker.h
@@ -0,0 +1,37 @@
+//===- MipsELFMCLinker.h --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MIPS_ELF_SECTION_LINKER_H
+#define MIPS_ELF_SECTION_LINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Target/ELFMCLinker.h>
+
+namespace mcld {
+
+class Module;
+class MemoryArea;
+
+/** \class MipsELFMCLinker
+ * \brief MipsELFMCLinker sets up the environment for linking.
+ */
+class MipsELFMCLinker : public ELFMCLinker
+{
+public:
+ MipsELFMCLinker(LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ MemoryArea& pOutput);
+
+ ~MipsELFMCLinker();
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/Mips/MipsELFSectLinker.cpp b/lib/Target/Mips/MipsELFSectLinker.cpp
deleted file mode 100644
index dedf505..0000000
--- a/lib/Target/Mips/MipsELFSectLinker.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- MipsELFSectLinker.cpp ----------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "MipsELFSectLinker.h"
-
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-MipsELFSectLinker::MipsELFSectLinker(SectLinkerOption &pOption,
- TargetLDBackend &pLDBackend)
- : SectLinker(pOption,
- pLDBackend) {
- MCLDInfo &info = pOption.info();
- // set up target-dependent constraints of attibutes
- info.attrFactory().constraint().enableWholeArchive();
- info.attrFactory().constraint().disableAsNeeded();
- info.attrFactory().constraint().setSharedSystem();
-
- // set up the predefined attributes
- info.attrFactory().predefined().setWholeArchive();
- info.attrFactory().predefined().setDynamic();
-}
-
-MipsELFSectLinker::~MipsELFSectLinker()
-{
-}
-
diff --git a/lib/Target/Mips/MipsELFSectLinker.h b/lib/Target/Mips/MipsELFSectLinker.h
deleted file mode 100644
index 1aacfef..0000000
--- a/lib/Target/Mips/MipsELFSectLinker.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- MipsELFSectLinker.h ------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef MIPS_ELF_SECTION_LINKER_H
-#define MIPS_ELF_SECTION_LINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/CodeGen/SectLinker.h>
-
-namespace mcld
-{
-
-/** \class MipsELFSectLinker
- * \brief MipsELFSectLinker sets up the environment for linking.
- */
-class MipsELFSectLinker : public SectLinker
-{
-public:
- MipsELFSectLinker(SectLinkerOption &pOption,
- mcld::TargetLDBackend &pLDBackend);
-
- ~MipsELFSectLinker();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/lib/Target/Mips/MipsEmulation.cpp b/lib/Target/Mips/MipsEmulation.cpp
new file mode 100644
index 0000000..74f2637
--- /dev/null
+++ b/lib/Target/Mips/MipsEmulation.cpp
@@ -0,0 +1,60 @@
+//===- MipsEmulation.cpp --------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "Mips.h"
+#include <mcld/LinkerConfig.h>
+#include <mcld/Target/ELFEmulation.h>
+#include <mcld/Support/TargetRegistry.h>
+
+namespace mcld {
+
+static bool MCLDEmulateMipsELF(LinkerConfig& pConfig)
+{
+ if (!MCLDEmulateELF(pConfig))
+ return false;
+
+ // set up target-dependent constraints of attributes
+ pConfig.attribute().constraint().enableWholeArchive();
+ pConfig.attribute().constraint().enableAsNeeded();
+ pConfig.attribute().constraint().setSharedSystem();
+
+ // set up the predefined attributes
+ pConfig.attribute().predefined().unsetWholeArchive();
+ pConfig.attribute().predefined().unsetAsNeeded();
+ pConfig.attribute().predefined().setDynamic();
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// emulateMipsLD - the help function to emulate Mips ld
+//===----------------------------------------------------------------------===//
+bool emulateMipsLD(const std::string& pTriple, LinkerConfig& pConfig)
+{
+ llvm::Triple theTriple(pTriple);
+ if (theTriple.isOSDarwin()) {
+ assert(0 && "MachO linker has not supported yet");
+ return false;
+ }
+ if (theTriple.isOSWindows()) {
+ assert(0 && "COFF linker has not supported yet");
+ return false;
+ }
+
+ return MCLDEmulateMipsELF(pConfig);
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// MipsEmulation
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeMipsEmulation() {
+ // Register the emulation
+ mcld::TargetRegistry::RegisterEmulation(mcld::TheMipselTarget, mcld::emulateMipsLD);
+}
+
diff --git a/lib/Target/Mips/MipsGOT.cpp b/lib/Target/Mips/MipsGOT.cpp
index 42ef972..b4eb1cd 100644
--- a/lib/Target/Mips/MipsGOT.cpp
+++ b/lib/Target/Mips/MipsGOT.cpp
@@ -24,26 +24,19 @@
//===----------------------------------------------------------------------===//
// MipsGOT
-MipsGOT::MipsGOT(LDSection& pSection, SectionData& pSectionData)
- : GOT(pSection, pSectionData, MipsGOTEntrySize),
+//===----------------------------------------------------------------------===//
+MipsGOT::MipsGOT(LDSection& pSection)
+ : GOT(pSection, MipsGOTEntrySize),
m_pLocalNum(0)
{
// Create GOT0 entries.
- for (size_t i = 0; i < MipsGOT0Num; ++i) {
- GOTEntry* entry =
- new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
-
- if (NULL == entry)
- fatal(diag::fail_allocate_memory_got);
-
- m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
- }
+ reserve(MipsGOT0Num);
// Skip GOT0 entries.
- iterator it = m_SectionData.begin();
+ iterator it = m_SectionData->begin();
for (size_t i = 1; i < MipsGOT0Num; ++i) {
- assert((it != m_SectionData.end()) &&
+ assert((it != m_SectionData->end()) &&
"Generation of GOT0 entries is incomplete!");
++it;
@@ -54,24 +47,9 @@
m_pLocalNum = MipsGOT0Num;
}
-MipsGOT::iterator MipsGOT::begin()
+bool MipsGOT::hasGOT1() const
{
- return m_SectionData.getFragmentList().begin();
-}
-
-MipsGOT::iterator MipsGOT::end()
-{
- return m_SectionData.getFragmentList().end();
-}
-
-MipsGOT::const_iterator MipsGOT::begin() const
-{
- return m_SectionData.getFragmentList().begin();
-}
-
-MipsGOT::const_iterator MipsGOT::end() const
-{
- return m_SectionData.getFragmentList().end();
+ return (m_SectionData->size() > MipsGOT0Num);
}
uint64_t MipsGOT::emit(MemoryRegion& pRegion)
@@ -83,29 +61,16 @@
uint64_t result = 0;
for (iterator it = begin(), ie = end();
it != ie; ++it, ++buffer) {
- GOTEntry* got = &(llvm::cast<GOTEntry>((*it)));
+ GOT::Entry* got = &(llvm::cast<GOT::Entry>((*it)));
*buffer = static_cast<uint32_t>(got->getContent());
result += entry_size;
}
return result;
}
-void MipsGOT::reserveEntry(size_t pNum)
-{
- for (size_t i = 0; i < pNum; ++i) {
- GOTEntry* entry =
- new (std::nothrow) GOTEntry(0, MipsGOTEntrySize, &m_SectionData);
-
- if (NULL == entry)
- fatal(diag::fail_allocate_memory_got);
-
- m_Section.setSize(m_Section.size() + MipsGOTEntrySize);
- }
-}
-
void MipsGOT::reserveLocalEntry()
{
- reserveEntry(1);
+ reserve(1);
++m_pLocalNum;
// Move global entries iterator forward.
@@ -115,42 +80,30 @@
void MipsGOT::reserveGlobalEntry()
{
- reserveEntry(1);
+ reserve(1);
}
-GOTEntry* MipsGOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
+GOT::Entry* MipsGOT::consumeLocal()
{
- if (isLocal(&pInfo) && pInfo.type() == ResolveInfo::Section) {
- pExist = false;
- iterator& it = m_LocalGOTIterator;
- ++it;
- assert(it != m_SectionData.getFragmentList().end() &&
- "The number of GOT Entries and ResolveInfo doesn't match");
- GOTEntry* entry = llvm::cast<GOTEntry>(&(*it));
- return entry;
- }
+ iterator& it = m_LocalGOTIterator;
+ ++it;
+ assert(it != m_SectionData->getFragmentList().end() &&
+ "The number of GOT Entries and ResolveInfo doesn't match");
+ return llvm::cast<GOT::Entry>(&(*it));
+}
- GOTEntry*& entry = m_GeneralGOTMap[&pInfo];
-
- pExist = NULL != entry;
-
- if (!pExist) {
- iterator& it = isLocal(&pInfo) ? m_LocalGOTIterator : m_GlobalGOTIterator;
-
- ++it;
-
- assert(it != m_SectionData.getFragmentList().end() &&
- "The number of GOT Entries and ResolveInfo doesn't match");
-
- entry = llvm::cast<GOTEntry>(&(*it));
- }
-
- return entry;
+GOT::Entry* MipsGOT::consumeGlobal()
+{
+ iterator& it = m_GlobalGOTIterator;
+ ++it;
+ assert(it != m_SectionData->getFragmentList().end() &&
+ "The number of GOT Entries and ResolveInfo doesn't match");
+ return llvm::cast<GOT::Entry>(&(*it));
}
size_t MipsGOT::getTotalNum() const
{
- return m_SectionData.getFragmentList().size();
+ return m_SectionData->getFragmentList().size();
}
size_t MipsGOT::getLocalNum() const
diff --git a/lib/Target/Mips/MipsGOT.h b/lib/Target/Mips/MipsGOT.h
index 23a3ded..6ec4926 100644
--- a/lib/Target/Mips/MipsGOT.h
+++ b/lib/Target/Mips/MipsGOT.h
@@ -15,7 +15,6 @@
#include <llvm/ADT/DenseMap.h>
#include <mcld/Target/GOT.h>
-#include <mcld/LD/SectionData.h>
namespace mcld
{
@@ -27,33 +26,20 @@
*/
class MipsGOT : public GOT
{
-private:
- typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
- typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolTypeMapType;
-
public:
- typedef SectionData::iterator iterator;
- typedef SectionData::const_iterator const_iterator;
-
-public:
- MipsGOT(LDSection& pSection, SectionData& pSectionData);
-
- iterator begin();
- iterator end();
-
- const_iterator begin() const;
- const_iterator end() const;
+ MipsGOT(LDSection& pSection);
uint64_t emit(MemoryRegion& pRegion);
void reserveLocalEntry();
void reserveGlobalEntry();
- GOTEntry* getEntry(const ResolveInfo& pInfo, bool& pExist);
-
size_t getTotalNum() const;
size_t getLocalNum() const;
+ GOT::Entry* consumeLocal();
+ GOT::Entry* consumeGlobal();
+
void setLocal(const ResolveInfo* pInfo) {
m_GOTTypeMap[pInfo] = false;
}
@@ -70,17 +56,18 @@
return m_GOTTypeMap[pInfo] == true;
}
+ /// hasGOT1 - return if this got section has any GOT1 entry
+ bool hasGOT1() const;
+
private:
- SymbolIndexMapType m_GeneralGOTMap; // Map ResolveInfo* to GOTEntry *.
+ typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolTypeMapType;
+
+private:
SymbolTypeMapType m_GOTTypeMap;
iterator m_LocalGOTIterator; // last local GOT entries
iterator m_GlobalGOTIterator; // last global GOT entries
size_t m_pLocalNum;
-
-private:
- // Use reserveLocalEntry()/reserveGlobalEntry() instead of this routine.
- void reserveEntry(size_t pNum = 1);
};
} // namespace of mcld
diff --git a/lib/Target/Mips/MipsLDBackend.cpp b/lib/Target/Mips/MipsLDBackend.cpp
index e8b68ea..da2399e 100644
--- a/lib/Target/Mips/MipsLDBackend.cpp
+++ b/lib/Target/Mips/MipsLDBackend.cpp
@@ -6,7 +6,6 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#include "Mips.h"
#include "MipsELFDynamic.h"
#include "MipsLDBackend.h"
@@ -15,14 +14,18 @@
#include <llvm/ADT/Triple.h>
#include <llvm/Support/ELF.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/SectionMap.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/MC/Attribute.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/Support/MemoryRegion.h>
+#include <mcld/Support/MemoryArea.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Support/TargetRegistry.h>
#include <mcld/Target/OutputRelocSection.h>
+#include <mcld/Object/ObjectBuilder.h>
enum {
// The original o32 abi.
@@ -35,10 +38,14 @@
E_MIPS_ABI_EABI64 = 0x00004000
};
-namespace mcld {
+using namespace mcld;
-MipsGNULDBackend::MipsGNULDBackend()
- : m_pRelocFactory(NULL),
+//===----------------------------------------------------------------------===//
+// MipsGNULDBackend
+//===----------------------------------------------------------------------===//
+MipsGNULDBackend::MipsGNULDBackend(const LinkerConfig& pConfig)
+ : GNULDBackend(pConfig),
+ m_pRelocFactory(NULL),
m_pGOT(NULL),
m_pRelDyn(NULL),
m_pDynamic(NULL),
@@ -49,32 +56,34 @@
MipsGNULDBackend::~MipsGNULDBackend()
{
- if (NULL != m_pRelocFactory)
- delete m_pRelocFactory;
- if (NULL != m_pGOT)
- delete m_pGOT;
- if (NULL != m_pRelDyn)
- delete m_pRelDyn;
- if (NULL != m_pDynamic)
- delete m_pDynamic;
+ delete m_pRelocFactory;
+ delete m_pGOT;
+ delete m_pRelDyn;
+ delete m_pDynamic;
}
-bool MipsGNULDBackend::initTargetSectionMap(SectionMap& pSectionMap)
+void MipsGNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
{
- // Nothing to do because we do not support
- // any MIPS specific sections now.
- return true;
+ if (LinkerConfig::Object != config().codeGenType()) {
+ ELFFileFormat* file_format = getOutputFormat();
+
+ // initialize .got
+ LDSection& got = file_format->getGOT();
+ m_pGOT = new MipsGOT(got);
+
+ // initialize .rel.dyn
+ LDSection& reldyn = file_format->getRelDyn();
+ m_pRelDyn = new OutputRelocSection(pModule,
+ reldyn,
+ getRelEntrySize());
+ }
}
-void MipsGNULDBackend::initTargetSections(MCLinker& pLinker)
-{
-}
-
-void MipsGNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
+void MipsGNULDBackend::initTargetSymbols(FragmentLinker& pLinker)
{
// Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
// same name in input
- m_pGOTSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
+ m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::AsRefered, FragmentLinker::Resolve>(
"_GLOBAL_OFFSET_TABLE_",
false,
ResolveInfo::Object,
@@ -82,10 +91,10 @@
ResolveInfo::Local,
0x0, // size
0x0, // value
- NULL, // FragRef
+ FragmentRef::Null(), // FragRef
ResolveInfo::Hidden);
- m_pGpDispSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
+ m_pGpDispSymbol = pLinker.defineSymbol<FragmentLinker::AsRefered, FragmentLinker::Resolve>(
"_gp_disp",
false,
ResolveInfo::Section,
@@ -93,7 +102,7 @@
ResolveInfo::Absolute,
0x0, // size
0x0, // value
- NULL, // FragRef
+ FragmentRef::Null(), // FragRef
ResolveInfo::Default);
if (NULL != m_pGpDispSymbol) {
@@ -101,11 +110,11 @@
}
}
-bool MipsGNULDBackend::initRelocFactory(const MCLinker& pLinker)
+bool MipsGNULDBackend::initRelocFactory(const FragmentLinker& pLinker)
{
if (NULL == m_pRelocFactory) {
m_pRelocFactory = new MipsRelocationFactory(1024, *this);
- m_pRelocFactory->setLayout(pLinker.getLayout());
+ m_pRelocFactory->setFragmentLinker(pLinker);
}
return true;
}
@@ -117,44 +126,43 @@
}
void MipsGNULDBackend::scanRelocation(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput,
+ FragmentLinker& pLinker,
+ Module& pModule,
const LDSection& pSection)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
- assert(NULL != pSection.getLink());
- if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) {
- if (rsym->isLocal()) {
- updateAddend(pReloc, pInputSym, pLinker.getLayout());
- }
- return;
- }
-
- // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies
- // that a .got section is needed.
- if (NULL == m_pGOT && NULL != m_pGOTSymbol) {
- if (rsym == m_pGOTSymbol->resolveInfo()) {
- createGOT(pLinker, pOutput);
- }
- }
-
// Skip relocation against _gp_disp
- if (strcmp("_gp_disp", pInputSym.name()) == 0)
+ if (NULL != m_pGpDispSymbol) {
+ if (pReloc.symInfo() == m_pGpDispSymbol->resolveInfo())
+ return;
+ }
+
+ pReloc.updateAddend();
+
+ if (0 == (pSection.flag() & llvm::ELF::SHF_ALLOC))
return;
// We test isLocal or if pInputSym is not a dynamic symbol
// We assume -Bsymbolic to bind all symbols internaly via !rsym->isDyn()
// Don't put undef symbols into local entries.
- if ((rsym->isLocal() || !isDynamicSymbol(pInputSym, pOutput) ||
+ if ((rsym->isLocal() || !isDynamicSymbol(*rsym) ||
!rsym->isDyn()) && !rsym->isUndef())
- scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
+ scanLocalReloc(pReloc, pLinker);
else
- scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
+ scanGlobalReloc(pReloc, pLinker);
+
+ // check if we shoule issue undefined reference for the relocation target
+ // symbol
+ if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak())
+ fatal(diag::undefined_reference) << rsym->name();
+
+ if ((rsym->reserved() & ReserveRel) != 0x0) {
+ // set hasTextRelSection if needed
+ checkAndSetHasTextRel(pSection);
+ }
}
uint32_t MipsGNULDBackend::machine() const
@@ -199,27 +207,33 @@
return 0x80000;
}
-uint64_t MipsGNULDBackend::abiPageSize(const MCLDInfo& pInfo) const
+uint64_t MipsGNULDBackend::abiPageSize() const
{
- if (pInfo.options().maxPageSize() > 0)
- return pInfo.options().maxPageSize();
+ if (config().options().maxPageSize() > 0)
+ return config().options().maxPageSize();
else
return static_cast<uint64_t>(0x10000);
}
-void MipsGNULDBackend::doPreLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker)
+void MipsGNULDBackend::doPreLayout(FragmentLinker& pLinker)
{
+ // set .got size
// when building shared object, the .got section is must.
- if (pOutput.type() == Output::DynObj && NULL == m_pGOT) {
- createGOT(pLinker, pOutput);
+ if (LinkerConfig::Object != config().codeGenType()) {
+ if (LinkerConfig::DynObj == config().codeGenType() ||
+ m_pGOT->hasGOT1() ||
+ NULL != m_pGOTSymbol) {
+ m_pGOT->finalizeSectionSize();
+ defineGOTSymbol(pLinker);
+ }
+
+ // set .rel.dyn size
+ if (!m_pRelDyn->empty())
+ m_pRelDyn->finalizeSectionSize();
}
}
-
-void MipsGNULDBackend::doPostLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker)
+void MipsGNULDBackend::doPostLayout(Module& pModule,
+ FragmentLinker& pLinker)
{
}
@@ -241,15 +255,12 @@
return *m_pDynamic;
}
-uint64_t MipsGNULDBackend::emitSectionData(const Output& pOutput,
- const LDSection& pSection,
- const MCLDInfo& pInfo,
- const Layout& pLayout,
+uint64_t MipsGNULDBackend::emitSectionData(const LDSection& pSection,
MemoryRegion& pRegion) const
{
assert(pRegion.size() && "Size of MemoryRegion is zero!");
- const ELFFileFormat* file_format = getOutputFormat(pOutput);
+ const ELFFileFormat* file_format = getOutputFormat();
if (&pSection == &(file_format->getGOT())) {
assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
@@ -269,58 +280,212 @@
m_GlobalGOTSyms.end(), &pSymbol) != m_GlobalGOTSyms.end();
}
-/// emitDynamicSymbol - emit dynamic symbol.
-void MipsGNULDBackend::emitDynamicSymbol(llvm::ELF::Elf32_Sym& sym32,
- Output& pOutput,
- LDSymbol& pSymbol,
- const Layout& pLayout,
- char* strtab,
- size_t strtabsize,
- size_t symtabIdx)
+/// sizeNamePools - compute the size of regular name pools
+/// In ELF executable files, regular name pools are .symtab, .strtab,
+/// .dynsym, .dynstr, .hash and .shstrtab.
+void
+MipsGNULDBackend::sizeNamePools(const Module& pModule, bool pIsStaticLink)
{
- // maintain output's symbol and index map
- bool sym_exist = false;
- HashTableType::entry_type* entry = 0;
- entry = m_pSymIndexMap->insert(&pSymbol, sym_exist);
- entry->setValue(symtabIdx);
+ // number of entries in symbol tables starts from 1 to hold the special entry
+ // at index 0 (STN_UNDEF). See ELF Spec Book I, p1-21.
+ size_t symtab = 1;
+ size_t dynsym = pIsStaticLink ? 0 : 1;
- // FIXME: check the endian between host and target
- // write out symbol
- sym32.st_name = strtabsize;
- sym32.st_value = pSymbol.value();
- sym32.st_size = getSymbolSize(pSymbol);
- sym32.st_info = getSymbolInfo(pSymbol);
- sym32.st_other = pSymbol.visibility();
- sym32.st_shndx = getSymbolShndx(pSymbol, pLayout);
- // write out string
- strcpy((strtab + strtabsize), pSymbol.name());
+ // size of string tables starts from 1 to hold the null character in their
+ // first byte
+ size_t strtab = 1;
+ size_t dynstr = pIsStaticLink ? 0 : 1;
+ size_t shstrtab = 1;
+ size_t hash = 0;
+
+ /// compute the size of .symtab, .dynsym and .strtab
+ /// @{
+ Module::const_sym_iterator symbol;
+ const Module::SymbolTable& symbols = pModule.getSymbolTable();
+ size_t str_size = 0;
+ // compute the size of symbols in Local and File category
+ Module::const_sym_iterator symEnd = symbols.localEnd();
+ for (symbol = symbols.localBegin(); symbol != symEnd; ++symbol) {
+ str_size = (*symbol)->nameSize() + 1;
+ if (!pIsStaticLink && isDynamicSymbol(**symbol)) {
+ ++dynsym;
+ if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+ dynstr += str_size;
+ }
+ ++symtab;
+ if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+ strtab += str_size;
+ }
+ // compute the size of symbols in TLS category
+ symEnd = symbols.tlsEnd();
+ for (symbol = symbols.tlsBegin(); symbol != symEnd; ++symbol) {
+ str_size = (*symbol)->nameSize() + 1;
+ if (!pIsStaticLink) {
+ ++dynsym;
+ if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+ dynstr += str_size;
+ }
+ ++symtab;
+ if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+ strtab += str_size;
+ }
+ // compute the size of the reset of symbols
+ symEnd = pModule.sym_end();
+ for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
+ str_size = (*symbol)->nameSize() + 1;
+ if (!pIsStaticLink && isDynamicSymbol(**symbol)) {
+ ++dynsym;
+ if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+ dynstr += str_size;
+ }
+ ++symtab;
+ if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+ strtab += str_size;
+ }
+
+ ELFFileFormat* file_format = getOutputFormat();
+
+ switch(config().codeGenType()) {
+ // compute size of .dynstr and .hash
+ case LinkerConfig::DynObj: {
+ // soname
+ if (!pIsStaticLink)
+ dynstr += pModule.name().size() + 1;
+ }
+ /** fall through **/
+ case LinkerConfig::Exec: {
+ // add DT_NEED strings into .dynstr and .dynamic
+ // Rules:
+ // 1. ignore --no-add-needed
+ // 2. force count in --no-as-needed
+ // 3. judge --as-needed
+ if (!pIsStaticLink) {
+ Module::const_lib_iterator lib, libEnd = pModule.lib_end();
+ for (lib = pModule.lib_begin(); lib != libEnd; ++lib) {
+ // --add-needed
+ if ((*lib)->attribute()->isAddNeeded()) {
+ // --no-as-needed
+ if (!(*lib)->attribute()->isAsNeeded()) {
+ dynstr += (*lib)->name().size() + 1;
+ dynamic().reserveNeedEntry();
+ }
+ // --as-needed
+ else if ((*lib)->isNeeded()) {
+ dynstr += (*lib)->name().size() + 1;
+ dynamic().reserveNeedEntry();
+ }
+ }
+ }
+
+ // compute .hash
+ // Both Elf32_Word and Elf64_Word are 4 bytes
+ hash = (2 + getHashBucketCount(dynsym, false) + dynsym) *
+ sizeof(llvm::ELF::Elf32_Word);
+ }
+
+ // set size
+ if (32 == bitclass())
+ file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf32_Sym));
+ else
+ file_format->getDynSymTab().setSize(dynsym*sizeof(llvm::ELF::Elf64_Sym));
+ file_format->getDynStrTab().setSize(dynstr);
+ file_format->getHashTab().setSize(hash);
+
+ }
+ /* fall through */
+ case LinkerConfig::Object: {
+ if (32 == bitclass())
+ file_format->getSymTab().setSize(symtab*sizeof(llvm::ELF::Elf32_Sym));
+ else
+ file_format->getSymTab().setSize(symtab*sizeof(llvm::ELF::Elf64_Sym));
+ file_format->getStrTab().setSize(strtab);
+ break;
+ }
+ default: {
+ fatal(diag::fatal_illegal_codegen_type) << pModule.name();
+ break;
+ }
+ } // end of switch
+ /// @}
+
+ /// reserve fixed entries in the .dynamic section.
+ /// @{
+ if (LinkerConfig::DynObj == config().codeGenType() ||
+ LinkerConfig::Exec == config().codeGenType()) {
+ // Because some entries in .dynamic section need information of .dynsym,
+ // .dynstr, .symtab, .strtab and .hash, we can not reserve non-DT_NEEDED
+ // entries until we get the size of the sections mentioned above
+ dynamic().reserveEntries(config(), *file_format);
+ file_format->getDynamic().setSize(dynamic().numOfBytes());
+ }
+ /// @}
+
+ /// compute the size of .shstrtab section.
+ /// @{
+ Module::const_iterator sect, sectEnd = pModule.end();
+ for (sect = pModule.begin(); sect != sectEnd; ++sect) {
+ // StackNote sections will always be in output!
+ if (0 != (*sect)->size() || LDFileFormat::StackNote == (*sect)->kind()) {
+ shstrtab += ((*sect)->name().size() + 1);
+ }
+ }
+ shstrtab += (strlen(".shstrtab") + 1);
+ file_format->getShStrTab().setSize(shstrtab);
+ /// @}
+}
+
+/// emitSymbol32 - emit an ELF32 symbol
+void MipsGNULDBackend::emitSymbol32(llvm::ELF::Elf32_Sym& pSym,
+ LDSymbol& pSymbol,
+ char* pStrtab,
+ size_t pStrtabsize,
+ size_t pSymtabIdx)
+{
+ // FIXME: check the endian between host and target
+ // write out symbol
+ if (ResolveInfo::Section != pSymbol.type() ||
+ &pSymbol == m_pGpDispSymbol) {
+ pSym.st_name = pStrtabsize;
+ strcpy((pStrtab + pStrtabsize), pSymbol.name());
+ }
+ else {
+ pSym.st_name = 0;
+ }
+ pSym.st_value = pSymbol.value();
+ pSym.st_size = getSymbolSize(pSymbol);
+ pSym.st_info = getSymbolInfo(pSymbol);
+ pSym.st_other = pSymbol.visibility();
+ pSym.st_shndx = getSymbolShndx(pSymbol);
}
/// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
///
/// the size of these tables should be computed before layout
/// layout should computes the start offset of these tables
-void MipsGNULDBackend::emitDynNamePools(Output& pOutput,
- SymbolCategory& pSymbols,
- const Layout& pLayout,
- const MCLDInfo& pLDInfo)
+void MipsGNULDBackend::emitDynNamePools(const Module& pModule,
+ MemoryArea& pOutput)
{
- assert(pOutput.hasMemArea());
- ELFFileFormat* file_format = getOutputFormat(pOutput);
+ ELFFileFormat* file_format = getOutputFormat();
+ if (!file_format->hasDynSymTab() ||
+ !file_format->hasDynStrTab() ||
+ !file_format->hasHashTab() ||
+ !file_format->hasDynamic())
+ return;
LDSection& symtab_sect = file_format->getDynSymTab();
LDSection& strtab_sect = file_format->getDynStrTab();
LDSection& hash_sect = file_format->getHashTab();
LDSection& dyn_sect = file_format->getDynamic();
- MemoryRegion* symtab_region = pOutput.memArea()->request(symtab_sect.offset(),
- symtab_sect.size());
- MemoryRegion* strtab_region = pOutput.memArea()->request(strtab_sect.offset(),
- strtab_sect.size());
- MemoryRegion* hash_region = pOutput.memArea()->request(hash_sect.offset(),
- hash_sect.size());
- MemoryRegion* dyn_region = pOutput.memArea()->request(dyn_sect.offset(),
- dyn_sect.size());
+ MemoryRegion* symtab_region = pOutput.request(symtab_sect.offset(),
+ symtab_sect.size());
+ MemoryRegion* strtab_region = pOutput.request(strtab_sect.offset(),
+ strtab_sect.size());
+ MemoryRegion* hash_region = pOutput.request(hash_sect.offset(),
+ hash_sect.size());
+ MemoryRegion* dyn_region = pOutput.request(dyn_sect.offset(),
+ dyn_sect.size());
+
// set up symtab_region
llvm::ELF::Elf32_Sym* symtab32 = NULL;
symtab32 = (llvm::ELF::Elf32_Sym*)symtab_region->start();
@@ -347,20 +512,67 @@
size_t strtabsize = 1;
// emit of .dynsym, and .dynstr except GOT entries
- for (SymbolCategory::iterator symbol = pSymbols.begin(),
- sym_end = pSymbols.end(); symbol != sym_end; ++symbol) {
- if (!isDynamicSymbol(**symbol, pOutput))
+ Module::const_sym_iterator symbol;
+ const Module::SymbolTable& symbols = pModule.getSymbolTable();
+ // emit symbol in File and Local category if it's dynamic symbol
+ Module::const_sym_iterator symEnd = symbols.localEnd();
+ for (symbol = symbols.localBegin(); symbol != symEnd; ++symbol) {
+ if (!isDynamicSymbol(**symbol))
continue;
if (isGlobalGOTSymbol(**symbol))
continue;
- emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
- strtabsize, symtabIdx);
+ emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+ symtabIdx);
+ // maintain output's symbol and index map
+ entry = m_pSymIndexMap->insert(*symbol, sym_exist);
+ entry->setValue(symtabIdx);
// sum up counters
++symtabIdx;
- strtabsize += (*symbol)->nameSize() + 1;
+ if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+ strtabsize += (*symbol)->nameSize() + 1;
+ }
+
+ // emit symbols in TLS category, all symbols in TLS category shold be emitited
+ // directly, except GOT entries
+ symEnd = symbols.tlsEnd();
+ for (symbol = symbols.tlsBegin(); symbol != symEnd; ++symbol) {
+ if (isGlobalGOTSymbol(**symbol))
+ continue;
+
+ emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+ symtabIdx);
+
+ // maintain output's symbol and index map
+ entry = m_pSymIndexMap->insert(*symbol, sym_exist);
+ entry->setValue(symtabIdx);
+ // sum up counters
+ ++symtabIdx;
+ if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+ strtabsize += (*symbol)->nameSize() + 1;
+ }
+
+ // emit the reset of the symbols if the symbol is dynamic symbol
+ symEnd = pModule.sym_end();
+ for (symbol = symbols.tlsEnd(); symbol != symEnd; ++symbol) {
+ if (!isDynamicSymbol(**symbol))
+ continue;
+
+ if (isGlobalGOTSymbol(**symbol))
+ continue;
+
+ emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+ symtabIdx);
+
+ // maintain output's symbol and index map
+ entry = m_pSymIndexMap->insert(*symbol, sym_exist);
+ entry->setValue(symtabIdx);
+ // sum up counters
+ ++symtabIdx;
+ if (ResolveInfo::Section != (*symbol)->type() || *symbol == m_pGpDispSymbol)
+ strtabsize += (*symbol)->nameSize() + 1;
}
// emit global GOT
@@ -371,15 +583,19 @@
// Make sure this golbal GOT entry is a dynamic symbol.
// If not, something is wrong earlier when putting this symbol into
// global GOT.
- if (!isDynamicSymbol(**symbol, pOutput))
+ if (!isDynamicSymbol(**symbol))
fatal(diag::mips_got_symbol) << (*symbol)->name();
- emitDynamicSymbol(symtab32[symtabIdx], pOutput, **symbol, pLayout, strtab,
- strtabsize, symtabIdx);
+ emitSymbol32(symtab32[symtabIdx], **symbol, strtab, strtabsize,
+ symtabIdx);
+ // maintain output's symbol and index map
+ entry = m_pSymIndexMap->insert(*symbol, sym_exist);
+ entry->setValue(symtabIdx);
// sum up counters
++symtabIdx;
- strtabsize += (*symbol)->nameSize() + 1;
+ if (ResolveInfo::Section != (*symbol)->type())
+ strtabsize += (*symbol)->nameSize() + 1;
}
// emit DT_NEED
@@ -389,38 +605,36 @@
// 2. force count in --no-as-needed
// 3. judge --as-needed
ELFDynamic::iterator dt_need = dynamic().needBegin();
- InputTree::const_bfs_iterator input, inputEnd = pLDInfo.inputs().bfs_end();
- for (input = pLDInfo.inputs().bfs_begin(); input != inputEnd; ++input) {
- if (Input::DynObj == (*input)->type()) {
- // --add-needed
- if ((*input)->attribute()->isAddNeeded()) {
- // --no-as-needed
- if (!(*input)->attribute()->isAsNeeded()) {
- strcpy((strtab + strtabsize), (*input)->name().c_str());
- (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
- strtabsize += (*input)->name().size() + 1;
- ++dt_need;
- }
- // --as-needed
- else if ((*input)->isNeeded()) {
- strcpy((strtab + strtabsize), (*input)->name().c_str());
- (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
- strtabsize += (*input)->name().size() + 1;
- ++dt_need;
- }
+ Module::const_lib_iterator lib, libEnd = pModule.lib_end();
+ for (lib = pModule.lib_begin(); lib != libEnd; ++lib) {
+ // --add-needed
+ if ((*lib)->attribute()->isAddNeeded()) {
+ // --no-as-needed
+ if (!(*lib)->attribute()->isAsNeeded()) {
+ strcpy((strtab + strtabsize), (*lib)->name().c_str());
+ (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
+ strtabsize += (*lib)->name().size() + 1;
+ ++dt_need;
+ }
+ // --as-needed
+ else if ((*lib)->isNeeded()) {
+ strcpy((strtab + strtabsize), (*lib)->name().c_str());
+ (*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
+ strtabsize += (*lib)->name().size() + 1;
+ ++dt_need;
}
}
} // for
// emit soname
// initialize value of ELF .dynamic section
- if (Output::DynObj == pOutput.type())
+ if (LinkerConfig::DynObj == config().codeGenType())
dynamic().applySoname(strtabsize);
- dynamic().applyEntries(pLDInfo, *file_format);
+ dynamic().applyEntries(config(), *file_format);
dynamic().emit(dyn_sect, *dyn_region);
- strcpy((strtab + strtabsize), pOutput.name().c_str());
- strtabsize += pOutput.name().size() + 1;
+ strcpy((strtab + strtabsize), pModule.name().c_str());
+ strtabsize += pModule.name().size() + 1;
// emit hash table
// FIXME: this verion only emit SVR4 hash section.
@@ -477,11 +691,9 @@
}
unsigned int
-MipsGNULDBackend::getTargetSectionOrder(const Output& pOutput,
- const LDSection& pSectHdr,
- const MCLDInfo& pInfo) const
+MipsGNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
{
- const ELFFileFormat* file_format = getOutputFormat(pOutput);
+ const ELFFileFormat* file_format = getOutputFormat();
if (&pSectHdr == &file_format->getGOT())
return SHO_DATA;
@@ -490,21 +702,20 @@
}
/// finalizeSymbol - finalize the symbol value
-bool MipsGNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
+bool MipsGNULDBackend::finalizeTargetSymbols(FragmentLinker& pLinker)
{
if (NULL != m_pGpDispSymbol)
- m_pGpDispSymbol->setValue(m_pGOT->getSection().addr() + 0x7FF0);
+ m_pGpDispSymbol->setValue(m_pGOT->addr() + 0x7FF0);
return true;
}
/// allocateCommonSymbols - allocate common symbols in the corresponding
-/// sections.
+/// sections. This is called at pre-layout stage.
/// @refer Google gold linker: common.cc: 214
/// FIXME: Mips needs to allocate small common symbol
-bool
-MipsGNULDBackend::allocateCommonSymbols(const MCLDInfo& pInfo, MCLinker& pLinker) const
+bool MipsGNULDBackend::allocateCommonSymbols(Module& pModule)
{
- SymbolCategory& symbol_list = pLinker.getOutputSymbols();
+ SymbolCategory& symbol_list = pModule.getSymbolTable();
if (symbol_list.emptyCommons() && symbol_list.emptyLocals())
return true;
@@ -514,44 +725,27 @@
// FIXME: If the order of common symbols is defined, then sort common symbols
// std::sort(com_sym, com_end, some kind of order);
- // get or create corresponding BSS LDSection
- LDSection* bss_sect = &pLinker.getOrCreateOutputSectHdr(".bss",
- LDFileFormat::BSS,
- llvm::ELF::SHT_NOBITS,
- llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-
- LDSection* tbss_sect = &pLinker.getOrCreateOutputSectHdr(
- ".tbss",
- LDFileFormat::BSS,
- llvm::ELF::SHT_NOBITS,
- llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
-
- // FIXME: .sbss amd .lbss currently unused.
- /*
- LDSection* sbss_sect = &pLinker.getOrCreateOutputSectHdr(
- ".sbss",
- LDFileFormat::BSS,
- llvm::ELF::SHT_NOBITS,
- llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC |
- llvm::ELF::SHF_MIPS_GPREL);
-
- LDSection* lbss_sect = &pLinker.getOrCreateOutputSectHdr(
- ".lbss",
- LDFileFormat::BSS,
- llvm::ELF::SHT_NOBITS,
- llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC |
- llvm::ELF::SHF_MIPS_LOCAL);
- */
-
- assert(NULL != bss_sect && NULL != tbss_sect);
+ // get corresponding BSS LDSection
+ ELFFileFormat* file_format = getOutputFormat();
+ LDSection& bss_sect = file_format->getBSS();
+ LDSection& tbss_sect = file_format->getTBSS();
// get or create corresponding BSS SectionData
- SectionData& bss_sect_data = pLinker.getOrCreateSectData(*bss_sect);
- SectionData& tbss_sect_data = pLinker.getOrCreateSectData(*tbss_sect);
+ SectionData* bss_sect_data = NULL;
+ if (bss_sect.hasSectionData())
+ bss_sect_data = bss_sect.getSectionData();
+ else
+ bss_sect_data = IRBuilder::CreateSectionData(bss_sect);
+
+ SectionData* tbss_sect_data = NULL;
+ if (tbss_sect.hasSectionData())
+ tbss_sect_data = tbss_sect.getSectionData();
+ else
+ tbss_sect_data = IRBuilder::CreateSectionData(tbss_sect);
// remember original BSS size
- uint64_t bss_offset = bss_sect->size();
- uint64_t tbss_offset = tbss_sect->size();
+ uint64_t bss_offset = bss_sect.size();
+ uint64_t tbss_offset = tbss_sect.size();
// allocate all local common symbols
com_end = symbol_list.localEnd();
@@ -565,19 +759,19 @@
// description here.
(*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
- (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
+ (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
// allocate TLS common symbol in tbss section
- tbss_offset += pLinker.getLayout().appendFragment(*frag,
- tbss_sect_data,
- (*com_sym)->value());
+ tbss_offset += ObjectBuilder::AppendFragment(*frag,
+ *tbss_sect_data,
+ (*com_sym)->value());
}
// FIXME: how to identify small and large common symbols?
else {
- bss_offset += pLinker.getLayout().appendFragment(*frag,
- bss_sect_data,
- (*com_sym)->value());
+ bss_offset += ObjectBuilder::AppendFragment(*frag,
+ *bss_sect_data,
+ (*com_sym)->value());
}
}
}
@@ -592,69 +786,48 @@
// description here.
(*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
- (*com_sym)->setFragmentRef(new FragmentRef(*frag, 0));
+ (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
// allocate TLS common symbol in tbss section
- tbss_offset += pLinker.getLayout().appendFragment(*frag,
- tbss_sect_data,
- (*com_sym)->value());
+ tbss_offset += ObjectBuilder::AppendFragment(*frag,
+ *tbss_sect_data,
+ (*com_sym)->value());
}
// FIXME: how to identify small and large common symbols?
else {
- bss_offset += pLinker.getLayout().appendFragment(*frag,
- bss_sect_data,
- (*com_sym)->value());
+ bss_offset += ObjectBuilder::AppendFragment(*frag,
+ *bss_sect_data,
+ (*com_sym)->value());
}
}
- bss_sect->setSize(bss_offset);
- tbss_sect->setSize(tbss_offset);
+ bss_sect.setSize(bss_offset);
+ tbss_sect.setSize(tbss_offset);
symbol_list.changeCommonsToGlobal();
return true;
}
-void MipsGNULDBackend::updateAddend(Relocation& pReloc,
- const LDSymbol& pInputSym,
- const Layout& pLayout) const
-{
- // Update value keep in addend if we meet a section symbol
- if (pReloc.symInfo()->type() == ResolveInfo::Section) {
- pReloc.setAddend(pLayout.getOutputOffset(
- *pInputSym.fragRef()) + pReloc.addend());
- }
-}
-
void MipsGNULDBackend::scanLocalReloc(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput)
+ FragmentLinker& pLinker)
{
ResolveInfo* rsym = pReloc.symInfo();
- updateAddend(pReloc, pInputSym, pLinker.getLayout());
-
switch (pReloc.type()){
case llvm::ELF::R_MIPS_NONE:
case llvm::ELF::R_MIPS_16:
break;
case llvm::ELF::R_MIPS_32:
- if (Output::DynObj == pOutput.type()) {
+ if (LinkerConfig::DynObj == config().codeGenType()) {
// TODO: (simon) The gold linker does not create an entry in .rel.dyn
// section if the symbol section flags contains SHF_EXECINSTR.
// 1. Find the reason of this condition.
// 2. Check this condition here.
- if (NULL == m_pRelDyn)
- createRelDyn(pLinker, pOutput);
-
m_pRelDyn->reserveEntry(*m_pRelocFactory);
rsym->setReserved(rsym->reserved() | ReserveRel);
// Remeber this rsym is a local GOT entry (as if it needs an entry).
// Actually we don't allocate an GOT entry.
- if (NULL == m_pGOT)
- createGOT(pLinker, pOutput);
m_pGOT->setLocal(rsym);
}
break;
@@ -686,9 +859,6 @@
break;
case llvm::ELF::R_MIPS_GOT16:
case llvm::ELF::R_MIPS_CALL16:
- if (NULL == m_pGOT)
- createGOT(pLinker, pOutput);
-
// For got16 section based relocations, we need to reserve got entries.
if (rsym->type() == ResolveInfo::Section) {
m_pGOT->reserveLocalEntry();
@@ -735,10 +905,7 @@
}
void MipsGNULDBackend::scanGlobalReloc(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput)
+ FragmentLinker& pLinker)
{
ResolveInfo* rsym = pReloc.symInfo();
@@ -759,17 +926,12 @@
case llvm::ELF::R_MIPS_64:
case llvm::ELF::R_MIPS_HI16:
case llvm::ELF::R_MIPS_LO16:
- if (symbolNeedsDynRel(*rsym, false, pLDInfo, pOutput, true)) {
- if (NULL == m_pRelDyn)
- createRelDyn(pLinker, pOutput);
-
+ if (symbolNeedsDynRel(pLinker, *rsym, false, true)) {
m_pRelDyn->reserveEntry(*m_pRelocFactory);
rsym->setReserved(rsym->reserved() | ReserveRel);
// Remeber this rsym is a global GOT entry (as if it needs an entry).
// Actually we don't allocate an GOT entry.
- if (NULL == m_pGOT)
- createGOT(pLinker, pOutput);
m_pGOT->setGlobal(rsym);
}
break;
@@ -782,9 +944,6 @@
case llvm::ELF::R_MIPS_CALL_LO16:
case llvm::ELF::R_MIPS_GOT_PAGE:
case llvm::ELF::R_MIPS_GOT_OFST:
- if (NULL == m_pGOT)
- createGOT(pLinker, pOutput);
-
if (!(rsym->reserved() & MipsGNULDBackend::ReserveGot)) {
m_pGOT->reserveGlobalEntry();
rsym->setReserved(rsym->reserved() | ReserveGot);
@@ -836,16 +995,11 @@
}
}
-void MipsGNULDBackend::createGOT(MCLinker& pLinker, const Output& pOutput)
+void MipsGNULDBackend::defineGOTSymbol(FragmentLinker& pLinker)
{
- ELFFileFormat* file_format = getOutputFormat(pOutput);
-
- LDSection& got = file_format->getGOT();
- m_pGOT = new MipsGOT(got, pLinker.getOrCreateSectData(got));
-
- // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
+ // define symbol _GLOBAL_OFFSET_TABLE_
if ( m_pGOTSymbol != NULL ) {
- pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
+ pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Unresolve>(
"_GLOBAL_OFFSET_TABLE_",
false,
ResolveInfo::Object,
@@ -853,11 +1007,11 @@
ResolveInfo::Local,
0x0, // size
0x0, // value
- pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+ FragmentRef::Create(*(m_pGOT->begin()), 0x0),
ResolveInfo::Hidden);
}
else {
- m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+ m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
"_GLOBAL_OFFSET_TABLE_",
false,
ResolveInfo::Object,
@@ -865,45 +1019,40 @@
ResolveInfo::Local,
0x0, // size
0x0, // value
- pLinker.getLayout().getFragmentRef(*(m_pGOT->begin()), 0x0),
+ FragmentRef::Create(*(m_pGOT->begin()), 0x0),
ResolveInfo::Hidden);
}
}
-void MipsGNULDBackend::createRelDyn(MCLinker& pLinker, const Output& pOutput)
+/// doCreateProgramHdrs - backend can implement this function to create the
+/// target-dependent segments
+void MipsGNULDBackend::doCreateProgramHdrs(Module& pModule,
+ const FragmentLinker& pLinker)
{
- ELFFileFormat* file_format = getOutputFormat(pOutput);
-
- // get .rel.dyn LDSection and create SectionData
- LDSection& reldyn = file_format->getRelDyn();
- // create SectionData and ARMRelDynSection
- m_pRelDyn = new OutputRelocSection(reldyn,
- pLinker.getOrCreateSectData(reldyn),
- 8);
+ // TODO
}
//===----------------------------------------------------------------------===//
/// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
///
static TargetLDBackend* createMipsLDBackend(const llvm::Target& pTarget,
- const std::string& pTriple)
+ const LinkerConfig& pConfig)
{
- llvm::Triple theTriple(pTriple);
- if (theTriple.isOSDarwin()) {
+ if (pConfig.triple().isOSDarwin()) {
assert(0 && "MachO linker is not supported yet");
}
- if (theTriple.isOSWindows()) {
+ if (pConfig.triple().isOSWindows()) {
assert(0 && "COFF linker is not supported yet");
}
- return new MipsGNULDBackend();
+ return new MipsGNULDBackend(pConfig);
}
-} // namespace of mcld
-
-//=============================
+//===----------------------------------------------------------------------===//
// Force static initialization.
-extern "C" void LLVMInitializeMipsLDBackend() {
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeMipsLDBackend() {
// Register the linker backend
mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget,
- mcld::createMipsLDBackend);
+ createMipsLDBackend);
}
+
diff --git a/lib/Target/Mips/MipsLDBackend.h b/lib/Target/Mips/MipsLDBackend.h
index 84f2277..b6adb93 100644
--- a/lib/Target/Mips/MipsLDBackend.h
+++ b/lib/Target/Mips/MipsLDBackend.h
@@ -8,15 +8,17 @@
//===----------------------------------------------------------------------===//
#ifndef MIPS_LDBACKEND_H
#define MIPS_LDBACKEND_H
-#include "mcld/Target/GNULDBackend.h"
+#include <mcld/Target/GNULDBackend.h>
#include "MipsELFDynamic.h"
#include "MipsGOT.h"
namespace mcld {
-class MCLinker;
+class LinkerConfig;
+class FragmentLinker;
class OutputRelocSection;
class SectionMap;
+class MemoryArea;
//===----------------------------------------------------------------------===//
/// MipsGNULDBackend - linker backend of Mips target of GNU ELF format
@@ -32,21 +34,18 @@
};
public:
- MipsGNULDBackend();
+ MipsGNULDBackend(const LinkerConfig& pConfig);
~MipsGNULDBackend();
public:
- /// initTargetSectionMap - initialize target dependent section mapping.
- bool initTargetSectionMap(SectionMap& pSectionMap);
-
/// initTargetSections - initialize target dependent sections in output
- void initTargetSections(MCLinker& pLinker);
+ void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
/// initTargetSymbols - initialize target dependent symbols in output.
- void initTargetSymbols(MCLinker& pLinker, const Output& pOutput);
+ void initTargetSymbols(FragmentLinker& pLinker);
/// initRelocFactory - create and initialize RelocationFactory.
- bool initRelocFactory(const MCLinker& pLinker);
+ bool initRelocFactory(const FragmentLinker& pLinker);
/// getRelocFactory - return relocation factory.
RelocationFactory* getRelocFactory();
@@ -55,10 +54,8 @@
/// create the empty entries if needed.
/// For Mips, the GOT, GP, and dynamic relocation entries are check to create.
void scanRelocation(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput,
+ FragmentLinker& pLinker,
+ Module& pModule,
const LDSection& pSection);
uint32_t machine() const;
@@ -79,17 +76,13 @@
uint64_t defaultTextSegmentAddr() const;
/// abiPageSize - the abi page size of the target machine
- uint64_t abiPageSize(const MCLDInfo& pInfo) const;
+ uint64_t abiPageSize() const;
/// preLayout - Backend can do any needed modification before layout
- void doPreLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker);
+ void doPreLayout(FragmentLinker& pLinker);
/// postLayout -Backend can do any needed modification after layout
- void doPostLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker);
+ void doPostLayout(Module& pModule, FragmentLinker& pLinker);
/// dynamic - the dynamic section of the target machine.
/// Use co-variant return type to return its own dynamic section.
@@ -110,23 +103,17 @@
/// - backend can maintain its own map<LDSection, table> to get the table
/// from given LDSection.
///
- /// @param pOutput - the output file
/// @param pSection - the given LDSection
- /// @param pInfo - all options in the command line.
- /// @param pLayout - for comouting the size of fragment
/// @param pRegion - the region to write out data
/// @return the size of the table in the file.
- uint64_t emitSectionData(const Output& pOutput,
- const LDSection& pSection,
- const MCLDInfo& pInfo,
- const Layout& pLayout,
+ uint64_t emitSectionData(const LDSection& pSection,
MemoryRegion& pRegion) const;
+ void sizeNamePools(const Module& pModule, bool pIsStaticLink);
+
/// emitNamePools - emit dynamic name pools - .dyntab, .dynstr, .hash
- virtual void emitDynNamePools(Output& pOutput,
- SymbolCategory& pSymbols,
- const Layout& pLayout,
- const MCLDInfo& pLDInfo);
+ void emitDynNamePools(const Module& pModule, MemoryArea& pOut);
+
MipsGOT& getGOT();
const MipsGOT& getGOT() const;
@@ -135,40 +122,41 @@
const OutputRelocSection& getRelDyn() const;
/// getTargetSectionOrder - compute the layout order of ARM target sections
- unsigned int getTargetSectionOrder(const Output& pOutput,
- const LDSection& pSectHdr,
- const MCLDInfo& pInfo) const;
+ unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
/// finalizeSymbol - finalize the symbol value
- bool finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput);
+ bool finalizeTargetSymbols(FragmentLinker& pLinker);
/// allocateCommonSymbols - allocate common symbols in the corresponding
/// sections.
- bool allocateCommonSymbols(const MCLDInfo& pLDInfo, MCLinker& pLinker) const;
+ bool allocateCommonSymbols(Module& pModule);
private:
- void scanLocalReloc(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput);
+ void scanLocalReloc(Relocation& pReloc, FragmentLinker& pLinker);
- void scanGlobalReloc(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput);
+ void scanGlobalReloc(Relocation& pReloc, FragmentLinker& pLinker);
- void createGOT(MCLinker& pLinker, const Output& pOutput);
- void createRelDyn(MCLinker& pLinker, const Output& pOutput);
+ void defineGOTSymbol(FragmentLinker& pLinker);
- /// updateAddend - update addend value of the relocation if the
- /// the target symbol is a section symbol. Addend is the offset
- /// in the section. This value should be updated after section
- /// merged.
- void updateAddend(Relocation& pReloc,
- const LDSymbol& pInputSym,
- const Layout& pLayout) const;
+ /// emitSymbol32 - emit an ELF32 symbol, override parent's function
+ void emitSymbol32(llvm::ELF::Elf32_Sym& pSym32,
+ LDSymbol& pSymbol,
+ char* pStrtab,
+ size_t pStrtabsize,
+ size_t pSymtabIdx);
+
+ /// getRelEntrySize - the size in BYTE of rel type relocation
+ size_t getRelEntrySize()
+ { return 8; }
+
+ /// getRelEntrySize - the size in BYTE of rela type relocation
+ size_t getRelaEntrySize()
+ { return 12; }
+
+ /// doCreateProgramHdrs - backend can implement this function to create the
+ /// target-dependent segments
+ virtual void doCreateProgramHdrs(Module& pModule,
+ const FragmentLinker& pLinker);
private:
RelocationFactory* m_pRelocFactory;
@@ -185,14 +173,7 @@
private:
/// isGlobalGOTSymbol - return true if the symbol is the global GOT entry.
bool isGlobalGOTSymbol(const LDSymbol& pSymbol) const;
- /// emitDynamicSymbol - emit dynamic symbol.
- void emitDynamicSymbol(llvm::ELF::Elf32_Sym& sym32,
- Output& pOutput,
- LDSymbol& pSymbol,
- const Layout& pLayout,
- char* strtab,
- size_t strtabsize,
- size_t symtabIdx);
+
};
} // namespace of mcld
diff --git a/lib/Target/Mips/MipsMCLinker.cpp b/lib/Target/Mips/MipsMCLinker.cpp
new file mode 100644
index 0000000..5805f12
--- /dev/null
+++ b/lib/Target/Mips/MipsMCLinker.cpp
@@ -0,0 +1,50 @@
+//===- MipsMCLinker.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "MipsELFMCLinker.h"
+
+#include "Mips.h"
+#include <llvm/ADT/Triple.h>
+#include <mcld/Module.h>
+#include <mcld/Support/TargetRegistry.h>
+
+using namespace mcld;
+
+namespace mcld {
+//===----------------------------------------------------------------------===//
+/// createMipsMCLinker - the help funtion to create
+//===----------------------------------------------------------------------===//
+/// corresponding MipsMCLinker
+///
+MCLinker* createMipsMCLinker(const std::string &pTriple,
+ LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ MemoryArea& pOutput)
+{
+ llvm::Triple theTriple(pTriple);
+ if (theTriple.isOSDarwin()) {
+ assert(0 && "MachO linker has not supported yet");
+ return NULL;
+ }
+ if (theTriple.isOSWindows()) {
+ assert(0 && "COFF linker has not supported yet");
+ return NULL;
+ }
+
+ return new MipsELFMCLinker(pConfig, pModule, pOutput);
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// MipsMCLinker
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeMipsMCLinker() {
+ // Register the linker frontend
+ mcld::TargetRegistry::RegisterMCLinker(TheMipselTarget, createMipsMCLinker);
+}
diff --git a/lib/Target/Mips/MipsRelocationFactory.cpp b/lib/Target/Mips/MipsRelocationFactory.cpp
index a9a34b2..09041be 100644
--- a/lib/Target/Mips/MipsRelocationFactory.cpp
+++ b/lib/Target/Mips/MipsRelocationFactory.cpp
@@ -9,9 +9,9 @@
#include <llvm/ADT/Twine.h>
#include <llvm/Support/ELF.h>
-#include <mcld/LD/Layout.h>
-#include <mcld/Target/OutputRelocSection.h>
+#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/Support/MsgHandling.h>
+#include <mcld/Target/OutputRelocSection.h>
#include "MipsRelocationFactory.h"
#include "MipsRelocationFunctions.h"
@@ -25,7 +25,6 @@
/// the prototype of applying function
typedef RelocationFactory::Result (*ApplyFunctionType)(Relocation&,
- const MCLDInfo& pLDInfo,
MipsRelocationFactory&);
// the table entry of applying functions
@@ -53,20 +52,17 @@
}
RelocationFactory::Result
-MipsRelocationFactory::applyRelocation(Relocation& pRelocation,
- const MCLDInfo& pLDInfo)
+MipsRelocationFactory::applyRelocation(Relocation& pRelocation)
{
Relocation::Type type = pRelocation.type();
if (type >= sizeof(ApplyFunctions) / sizeof(ApplyFunctions[0])) {
- fatal(diag::unknown_relocation) << (int)type
- << pRelocation.symInfo()->name();
return Unknown;
}
// apply the relocation
- return ApplyFunctions[type].func(pRelocation, pLDInfo, *this);
+ return ApplyFunctions[type].func(pRelocation, *this);
}
const char* MipsRelocationFactory::getName(Relocation::Type pType) const
@@ -107,11 +103,11 @@
static
RelocationFactory::Address helper_GetGP(MipsRelocationFactory& pParent)
{
- return pParent.getTarget().getGOT().getSection().addr() + 0x7FF0;
+ return pParent.getTarget().getGOT().addr() + 0x7FF0;
}
static
-GOTEntry& helper_GetGOTEntry(Relocation& pReloc,
+GOT::Entry& helper_GetGOTEntry(Relocation& pReloc,
MipsRelocationFactory& pParent,
bool& pExist, int32_t value)
{
@@ -120,22 +116,34 @@
MipsGNULDBackend& ld_backend = pParent.getTarget();
MipsGOT& got = ld_backend.getGOT();
- GOTEntry& got_entry = *got.getEntry(*rsym, pExist);
-
- if (pExist)
- return got_entry;
-
- // If we first get this GOT entry, we should initialize it.
- if (!(got.isLocal(rsym) && rsym->type() == ResolveInfo::Section)) {
- if (rsym->reserved() & MipsGNULDBackend::ReserveGot) {
- got_entry.setContent(pReloc.symValue());
- }
- else {
- fatal(diag::reserve_entry_number_mismatch_got);
- }
+ if (got.isLocal(rsym) && ResolveInfo::Section == rsym->type()) {
+ // Local section symbols consume local got entries.
+ return *got.consumeLocal();
}
- return got_entry;
+ GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+ if (NULL != got_entry) {
+ // found a mapping, then return the mapped entry immediately
+ return *got_entry;
+ }
+
+ // not found
+ if (got.isLocal(rsym))
+ got_entry = got.consumeLocal();
+ else
+ got_entry = got.consumeGlobal();
+
+ pParent.getSymGOTMap().record(*rsym, *got_entry);
+
+ // If we first get this GOT entry, we should initialize it.
+ if (rsym->reserved() & MipsGNULDBackend::ReserveGot) {
+ got_entry->setContent(pReloc.symValue());
+ }
+ else {
+ fatal(diag::reserve_entry_number_mismatch_got);
+ }
+
+ return *got_entry;
}
static
@@ -143,8 +151,8 @@
MipsRelocationFactory& pParent)
{
bool exist;
- GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0);
- return pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0;
+ GOT::Entry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, 0);
+ return got_entry.getOffset() - 0x7FF0;
}
static
@@ -160,7 +168,8 @@
int32_t AHI = pHiReloc.target();
int32_t ALO = pLoReloc.target();
- int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) + pLoReloc.addend();
+ int32_t AHL = ((AHI & 0xFFFF) << 16) + (int16_t)(ALO & 0xFFFF) +
+ pLoReloc.addend();
return AHL;
}
@@ -172,9 +181,7 @@
MipsGNULDBackend& ld_backend = pParent.getTarget();
MipsGOT& got = ld_backend.getGOT();
- bool exist;
- Relocation& rel_entry =
- *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
+ Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
rel_entry.setType(llvm::ELF::R_MIPS_REL32);
rel_entry.targetRef() = pReloc.targetRef();
@@ -200,7 +207,6 @@
// R_MIPS_NONE and those unsupported/deprecated relocation type
static
MipsRelocationFactory::Result none(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
MipsRelocationFactory& pParent)
{
return MipsRelocationFactory::OK;
@@ -209,7 +215,6 @@
// R_MIPS_32: S + A
static
MipsRelocationFactory::Result abs32(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
MipsRelocationFactory& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
@@ -217,12 +222,10 @@
RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
RelocationFactory::DWord S = pReloc.symValue();
- const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
- *(pReloc.targetRef().frag()));
- assert(NULL != target_sect);
+ LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
// If the flag of target section is not ALLOC, we will not scan this relocation
// but perform static relocation. (e.g., applying .debug section)
- if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+ if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
pReloc.target() = S + A;
return MipsRelocationFactory::OK;
}
@@ -243,7 +246,6 @@
// _gp_disp : ((AHL + GP - P) - (short)(AHL + GP - P)) >> 16
static
MipsRelocationFactory::Result hi16(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
MipsRelocationFactory& pParent)
{
Relocation* lo_reloc = helper_FindLo16Reloc(pReloc);
@@ -255,7 +257,7 @@
pParent.setAHL(AHL);
if (helper_isGpDisp(pReloc)) {
- int32_t P = pReloc.place(pParent.getLayout());
+ int32_t P = pReloc.place();
int32_t GP = helper_GetGP(pParent);
res = ((AHL + GP - P) - (int16_t)(AHL + GP - P)) >> 16;
}
@@ -275,13 +277,12 @@
// _gp_disp : AHL + GP - P + 4
static
MipsRelocationFactory::Result lo16(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
MipsRelocationFactory& pParent)
{
int32_t res = 0;
if (helper_isGpDisp(pReloc)) {
- int32_t P = pReloc.place(pParent.getLayout());
+ int32_t P = pReloc.place();
int32_t GP = helper_GetGP(pParent);
int32_t AHL = pParent.getAHL();
res = AHL + GP - P + 4;
@@ -306,7 +307,6 @@
// external: G
static
MipsRelocationFactory::Result got16(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
MipsRelocationFactory& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
@@ -323,10 +323,10 @@
int32_t res = (AHL + S + 0x8000) & 0xFFFF0000;
bool exist;
- GOTEntry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res);
+ GOT::Entry& got_entry = helper_GetGOTEntry(pReloc, pParent, exist, res);
got_entry.setContent(res);
- G = pParent.getLayout().getOutputOffset(got_entry) - 0x7FF0;
+ G = got_entry.getOffset() - 0x7FF0;
}
else {
G = helper_GetGOTOffset(pReloc, pParent);
@@ -341,7 +341,6 @@
// R_MIPS_CALL16: G
static
MipsRelocationFactory::Result call16(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
MipsRelocationFactory& pParent)
{
RelocationFactory::Address G = helper_GetGOTOffset(pReloc, pParent);
@@ -355,7 +354,6 @@
// R_MIPS_GPREL32: A + S + GP0 - GP
static
MipsRelocationFactory::Result gprel32(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
MipsRelocationFactory& pParent)
{
// Remember to add the section offset to A.
diff --git a/lib/Target/Mips/MipsRelocationFactory.h b/lib/Target/Mips/MipsRelocationFactory.h
index a1c7b5d..6076416 100644
--- a/lib/Target/Mips/MipsRelocationFactory.h
+++ b/lib/Target/Mips/MipsRelocationFactory.h
@@ -14,10 +14,10 @@
#include <mcld/LD/RelocationFactory.h>
#include <mcld/Support/GCFactory.h>
+#include <mcld/Target/SymbolEntryMap.h>
#include "MipsLDBackend.h"
-namespace mcld
-{
+namespace mcld {
/** \class MipsRelocationFactory
* \brief MipsRelocationFactory creates and destroys the Mips relocations.
@@ -25,9 +25,12 @@
class MipsRelocationFactory : public RelocationFactory
{
public:
+ typedef SymbolEntryMap<GOT::Entry> SymGOTMap;
+
+public:
MipsRelocationFactory(size_t pNum, MipsGNULDBackend& pParent);
- Result applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo);
+ Result applyRelocation(Relocation& pRelocation);
MipsGNULDBackend& getTarget()
{ return m_Target; }
@@ -45,9 +48,13 @@
const char* getName(Relocation::Type pType) const;
+ const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; }
+ SymGOTMap& getSymGOTMap() { return m_SymGOTMap; }
+
private:
MipsGNULDBackend& m_Target;
int32_t m_AHL;
+ SymGOTMap m_SymGOTMap;
};
} // namespace of mcld
diff --git a/lib/Target/Mips/MipsRelocationFunctions.h b/lib/Target/Mips/MipsRelocationFunctions.h
index 4b60d10..adff43f 100644
--- a/lib/Target/Mips/MipsRelocationFunctions.h
+++ b/lib/Target/Mips/MipsRelocationFunctions.h
@@ -9,7 +9,6 @@
#define DECL_MIPS_APPLY_RELOC_FUNC(Name) \
static MipsRelocationFactory::Result Name(Relocation& pEntry, \
- const MCLDInfo& pLDInfo, \
MipsRelocationFactory& pParent);
#define DECL_MIPS_APPLY_RELOC_FUNCS \
diff --git a/lib/Target/Mips/MipsSectLinker.cpp b/lib/Target/Mips/MipsSectLinker.cpp
deleted file mode 100644
index ed04edd..0000000
--- a/lib/Target/Mips/MipsSectLinker.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- MipsSectLinker.cpp -------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <llvm/ADT/Triple.h>
-#include <mcld/Support/TargetRegistry.h>
-#include "Mips.h"
-#include "MipsELFSectLinker.h"
-
-using namespace mcld;
-
-namespace mcld {
-//===----------------------------------------------------------------------===//
-/// createMipsSectLinker - the help funtion to create
-/// corresponding MipsSectLinker
-///
-SectLinker* createMipsSectLinker(const std::string &pTriple,
- SectLinkerOption &pOption,
- mcld::TargetLDBackend &pLDBackend)
-{
- llvm::Triple theTriple(pTriple);
- if (theTriple.isOSDarwin()) {
- assert(0 && "MachO linker has not supported yet");
- return NULL;
- }
- if (theTriple.isOSWindows()) {
- assert(0 && "COFF linker has not supported yet");
- return NULL;
- }
-
- return new MipsELFSectLinker(pOption, pLDBackend);
-}
-
-} // namespace of mcld
-
-//==========================
-// MipsSectLinker
-extern "C" void LLVMInitializeMipsSectLinker() {
- // Register the linker frontend
- mcld::TargetRegistry::RegisterSectLinker(TheMipselTarget,
- createMipsSectLinker);
-}
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
index 0987585..03db780 100644
--- a/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -6,14 +6,13 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#include "MipsTargetMachine.h"
-#include "mcld/Target/TargetMachine.h"
-#include "mcld/Support/TargetRegistry.h"
-#include "mcld/MC/MCLDInfo.h"
-#include "Mips.h"
-extern "C" void LLVMInitializeMipsLDTarget() {
+#include "Mips.h"
+#include <mcld/Target/TargetMachine.h>
+#include <mcld/Support/TargetRegistry.h>
+
+extern "C" void MCLDInitializeMipsLDTarget() {
// Register createTargetMachine function pointer to mcld::Target
mcld::RegisterTargetMachine<mcld::MipsBaseTargetMachine>
X(mcld::TheMipselTarget);
@@ -22,13 +21,9 @@
mcld::MipsBaseTargetMachine::MipsBaseTargetMachine(llvm::TargetMachine& pPM,
const mcld::Target &pTarget,
const std::string& pTriple)
- : mcld::LLVMTargetMachine(pPM, pTarget, pTriple) {
- // arg1 - the number of total attributes
- // arg2 - the most possible number of input files
- m_pLDInfo = new MCLDInfo(pTriple, 32, 64);
+ : mcld::MCLDTargetMachine(pPM, pTarget, pTriple) {
}
mcld::MipsBaseTargetMachine::~MipsBaseTargetMachine()
{
- delete m_pLDInfo;
}
diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h
index e9bd5da..6cfae73 100644
--- a/lib/Target/Mips/MipsTargetMachine.h
+++ b/lib/Target/Mips/MipsTargetMachine.h
@@ -8,29 +8,20 @@
//===----------------------------------------------------------------------===//
#ifndef MIPS_TARGET_MACHINE_H
#define MIPS_TARGET_MACHINE_H
-#include "mcld/Target/TargetMachine.h"
+
#include "Mips.h"
+#include <mcld/Target/TargetMachine.h>
-namespace mcld
+namespace mcld {
+
+class MipsBaseTargetMachine : public MCLDTargetMachine
{
-
-class MipsBaseTargetMachine : public LLVMTargetMachine
-{
-protected:
- MCLDInfo *m_pLDInfo;
-
public:
MipsBaseTargetMachine(llvm::TargetMachine &pTM,
const mcld::Target &pTarget,
const std::string &pTriple);
virtual ~MipsBaseTargetMachine();
-
- mcld::MCLDInfo& getLDInfo()
- { return *m_pLDInfo; }
-
- const mcld::MCLDInfo& getLDInfo() const
- { return *m_pLDInfo; }
};
} // namespace of mcld
diff --git a/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp b/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
index 0889973..3991c45 100644
--- a/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
+++ b/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp
@@ -13,7 +13,7 @@
mcld::Target TheMipselTarget;
-extern "C" void LLVMInitializeMipsLDTargetInfo() {
+extern "C" void MCLDInitializeMipsLDTargetInfo() {
// register into mcld::TargetRegistry
mcld::RegisterTarget X(TheMipselTarget, "mipsel");
}
diff --git a/lib/Target/OutputRelocSection.cpp b/lib/Target/OutputRelocSection.cpp
index c5bb9a8..593bdb9 100644
--- a/lib/Target/OutputRelocSection.cpp
+++ b/lib/Target/OutputRelocSection.cpp
@@ -7,26 +7,31 @@
//
//===----------------------------------------------------------------------===//
-#include <mcld/Target/OutputRelocSection.h>
-
#include <llvm/Support/Casting.h>
#include <mcld/LD/LDSection.h>
+#include <mcld/LD/RelocationFactory.h>
+#include <mcld/Module.h>
#include <mcld/Support/MsgHandling.h>
+#include <mcld/Target/OutputRelocSection.h>
+#include <mcld/IRBuilder.h>
using namespace mcld;
//===----------------------------------------------------------------------===//
// OutputRelocSection
//===----------------------------------------------------------------------===//
-OutputRelocSection::OutputRelocSection(LDSection& pSection,
- SectionData& pSectionData,
+OutputRelocSection::OutputRelocSection(Module& pModule,
+ LDSection& pSection,
unsigned int pEntrySize)
- : m_pSection(&pSection),
- m_pSectionData(&pSectionData),
+ : m_Module(pModule),
+ m_pSection(&pSection),
+ m_pRelocData(NULL),
m_EntryBytes(pEntrySize),
m_isVisit(false),
m_ValidEntryIterator(){
+ assert(!pSection.hasRelocData() && "Given section is not a relocation section");
+ m_pRelocData = IRBuilder::CreateRelocData(pSection);
}
OutputRelocSection::~OutputRelocSection()
@@ -37,52 +42,45 @@
size_t pNum)
{
for(size_t i=0; i<pNum; i++) {
- m_pSectionData->getFragmentList().push_back(pRelFactory.produceEmptyEntry());
+ m_pRelocData->getFragmentList().push_back(
+ pRelFactory.produceEmptyEntry());
// update section size
m_pSection->setSize(m_pSection->size() + m_EntryBytes);
}
}
-Relocation* OutputRelocSection::getEntry(const ResolveInfo& pSymbol,
- bool isForGOT,
- bool& pExist)
+Relocation* OutputRelocSection::consumeEntry()
{
// first time visit this function, set m_ValidEntryIterator to
// Fragments.begin()
if(!m_isVisit) {
- assert( !m_pSectionData->getFragmentList().empty() &&
+ assert(!m_pRelocData->getFragmentList().empty() &&
"DynRelSection contains no entries.");
- m_ValidEntryIterator = m_pSectionData->getFragmentList().begin();
+ m_ValidEntryIterator = m_pRelocData->getFragmentList().begin();
m_isVisit = true;
}
-
- assert(m_ValidEntryIterator != m_pSectionData->end() &&
- "No empty relocation entry for the incoming symbol.");
-
- // if this relocation is used to relocate GOT (.got or .got.plt),
- // check if we've gotten an entry for this symbol before. If yes,
- // return the found entry in map.
- // Otherwise, this relocation is used to relocate general section
- // (data or text section), return an empty entry directly.
- Relocation* result;
-
- if(isForGOT) {
- // get or create entry in m_SymRelMap
- Relocation *&entry = m_SymRelMap[&pSymbol];
- pExist = true;
-
- if(NULL == entry) {
- pExist = false;
- entry = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
- ++m_ValidEntryIterator;
- }
- result = entry;
- }
else {
- pExist = false;
- result = llvm::cast<Relocation>(&(*m_ValidEntryIterator));
+ // Add m_ValidEntryIterator here instead of at the end of this function.
+ // We may reserve an entry and then consume it immediately, e.g. for COPY
+ // relocation, so we need to avoid setting this iterator to
+ // RelocData->end() in any case, or when reserve and consume again,
+ // ++m_ValidEntryIterator will still be RelocData->end().
++m_ValidEntryIterator;
}
+ assert(m_ValidEntryIterator != m_pRelocData->end() &&
+ "No empty relocation entry for the incoming symbol.");
+
+ Relocation* result = &llvm::cast<Relocation>(*m_ValidEntryIterator);
return result;
}
+void OutputRelocSection::finalizeSectionSize()
+{
+ m_pSection->setSize(m_pRelocData->size() * m_EntryBytes);
+}
+
+bool OutputRelocSection::addSymbolToDynSym(LDSymbol& pSymbol)
+{
+ m_Module.getSymbolTable().changeLocalToTLS(pSymbol);
+ return true;
+}
diff --git a/lib/Target/PLT.cpp b/lib/Target/PLT.cpp
index 782d974..a8b515c 100644
--- a/lib/Target/PLT.cpp
+++ b/lib/Target/PLT.cpp
@@ -8,21 +8,22 @@
//===----------------------------------------------------------------------===//
#include <mcld/Target/PLT.h>
+#include <mcld/IRBuilder.h>
using namespace mcld;
class GOT;
//===----------------------------------------------------------------------===//
-// PLTEntry
+// PLT::Entry
//===----------------------------------------------------------------------===//
-PLTEntry::PLTEntry(size_t pSize, SectionData* pParent)
- : TargetFragment(Fragment::Target, pParent),
- m_EntrySize(pSize), m_pContent(NULL)
+PLT::Entry::Entry(size_t pSize, SectionData& pParent)
+ : TargetFragment(Fragment::Target, &pParent),
+ m_EntrySize(pSize), m_pContent(NULL)
{
}
-PLTEntry::~PLTEntry()
+PLT::Entry::~Entry()
{
if (m_pContent) {
free(m_pContent);
@@ -33,10 +34,10 @@
//===----------------------------------------------------------------------===//
// PLT
//===----------------------------------------------------------------------===//
-PLT::PLT(LDSection& pSection, SectionData& pSectionData)
- :m_Section(pSection),
- m_SectionData(pSectionData)
+PLT::PLT(LDSection& pSection)
+ :m_Section(pSection)
{
+ m_SectionData = IRBuilder::CreateSectionData(pSection);
}
PLT::~PLT()
diff --git a/lib/Target/Stub.cpp b/lib/Target/Stub.cpp
deleted file mode 100644
index 4b59acf..0000000
--- a/lib/Target/Stub.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-//===- Stub.cpp -----------------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "mcld/Target/Stub.h"
-
-using namespace mcld;
-
-//==========================
-// Stub
-
diff --git a/lib/Target/Target.cpp b/lib/Target/Target.cpp
index ec8dc87..ba69e03 100644
--- a/lib/Target/Target.cpp
+++ b/lib/Target/Target.cpp
@@ -15,7 +15,7 @@
mcld::Target::Target()
: TargetMachineCtorFn(NULL),
- SectLinkerCtorFn(NULL),
+ MCLinkerCtorFn(NULL),
TargetLDBackendCtorFn(NULL),
DiagnosticLineInfoCtorFn(NULL),
m_pT(NULL)
diff --git a/lib/Target/TargetLDBackend.cpp b/lib/Target/TargetLDBackend.cpp
index 4eda0a6..e955916 100644
--- a/lib/Target/TargetLDBackend.cpp
+++ b/lib/Target/TargetLDBackend.cpp
@@ -6,32 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "mcld/LD/Relocation.h"
-#include "mcld/LD/Layout.h"
-#include "mcld/Target/TargetLDBackend.h"
+#include <mcld/Target/TargetLDBackend.h>
+#include <mcld/LinkerConfig.h>
using namespace mcld;
-/* ** */
-TargetLDBackend::TargetLDBackend()
- : m_pEhFrame(NULL) {
+TargetLDBackend::TargetLDBackend(const LinkerConfig& pConfig)
+ : m_Config(pConfig) {
}
TargetLDBackend::~TargetLDBackend()
{
- if (NULL != m_pEhFrame)
- delete m_pEhFrame;
}
-EhFrame* TargetLDBackend::getEhFrame()
-{
- if (NULL == m_pEhFrame)
- m_pEhFrame = new EhFrame();
- return m_pEhFrame;
-}
-
-const EhFrame* TargetLDBackend::getEhFrame() const
-{
- assert(NULL == m_pEhFrame);
- return m_pEhFrame;
-}
diff --git a/lib/Target/X86/Android.mk b/lib/Target/X86/Android.mk
index 2272632..cf7ea17 100644
--- a/lib/Target/X86/Android.mk
+++ b/lib/Target/X86/Android.mk
@@ -3,13 +3,14 @@
mcld_x86_target_SRC_FILES := \
X86Diagnostic.cpp \
X86ELFDynamic.cpp \
- X86ELFSectLinker.cpp \
+ X86ELFMCLinker.cpp \
+ X86Emulation.cpp \
X86GOT.cpp \
X86GOTPLT.cpp \
X86LDBackend.cpp \
+ X86MCLinker.cpp \
X86PLT.cpp \
X86RelocationFactory.cpp \
- X86SectLinker.cpp \
X86TargetMachine.cpp
# For the host
diff --git a/lib/Target/X86/TargetInfo/X86TargetInfo.cpp b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
index afe349e..0985c02 100644
--- a/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
+++ b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
@@ -13,7 +13,7 @@
mcld::Target TheX86Target;
-extern "C" void LLVMInitializeX86LDTargetInfo() {
+extern "C" void MCLDInitializeX86LDTargetInfo() {
// register into mcld::TargetRegistry
mcld::RegisterTarget X(TheX86Target, "x86");
}
diff --git a/lib/Target/X86/X86Diagnostic.cpp b/lib/Target/X86/X86Diagnostic.cpp
index 98f0234..7191596 100644
--- a/lib/Target/X86/X86Diagnostic.cpp
+++ b/lib/Target/X86/X86Diagnostic.cpp
@@ -31,7 +31,7 @@
//==========================
// InitializeX86Diagnostic
-extern "C" void LLVMInitializeX86DiagnosticLineInfo() {
+extern "C" void MCLDInitializeX86DiagnosticLineInfo() {
// Register the linker frontend
mcld::TargetRegistry::RegisterDiagnosticLineInfo(TheX86Target, createX86DiagLineInfo);
}
diff --git a/lib/Target/X86/X86ELFMCLinker.cpp b/lib/Target/X86/X86ELFMCLinker.cpp
new file mode 100644
index 0000000..868d61c
--- /dev/null
+++ b/lib/Target/X86/X86ELFMCLinker.cpp
@@ -0,0 +1,23 @@
+//===- X86ELFMCLinker.cpp -------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "X86ELFMCLinker.h"
+#include <mcld/LinkerConfig.h>
+
+using namespace mcld;
+
+X86ELFMCLinker::X86ELFMCLinker(LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ MemoryArea& pOutput)
+ : ELFMCLinker(pConfig, pModule, pOutput) {
+}
+
+X86ELFMCLinker::~X86ELFMCLinker()
+{
+}
+
diff --git a/lib/Target/X86/X86ELFMCLinker.h b/lib/Target/X86/X86ELFMCLinker.h
new file mode 100644
index 0000000..173f7dc
--- /dev/null
+++ b/lib/Target/X86/X86ELFMCLinker.h
@@ -0,0 +1,39 @@
+//===- X86ELFMCLinker.h ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef X86_ELFSECTLINKER_H
+#define X86_ELFSECTLINKER_H
+#ifdef ENABLE_UNITTEST
+#include <gtest.h>
+#endif
+#include <mcld/Target/ELFMCLinker.h>
+
+namespace mcld {
+
+class Module;
+class MemoryArea;
+
+/** \class X86ELFMCLinker
+ * \brief X86ELFMCLinker sets up the environment for linking.
+ *
+ * \see
+ */
+class X86ELFMCLinker : public ELFMCLinker
+{
+public:
+ X86ELFMCLinker(LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ MemoryArea& pOutput);
+
+ ~X86ELFMCLinker();
+};
+
+} // namespace of mcld
+
+#endif
+
diff --git a/lib/Target/X86/X86ELFSectLinker.cpp b/lib/Target/X86/X86ELFSectLinker.cpp
deleted file mode 100644
index 009293c..0000000
--- a/lib/Target/X86/X86ELFSectLinker.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- X86ELFSectLinker.cpp -----------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include "X86ELFSectLinker.h"
-
-#include <mcld/CodeGen/SectLinkerOption.h>
-
-using namespace mcld;
-
-X86ELFSectLinker::X86ELFSectLinker(SectLinkerOption &pOption,
- TargetLDBackend &pLDBackend)
- : SectLinker(pOption,
- pLDBackend) {
- MCLDInfo &info = pOption.info();
- // set up target-dependent constraints of attibutes
- info.attrFactory().constraint().enableWholeArchive();
- info.attrFactory().constraint().disableAsNeeded();
- info.attrFactory().constraint().setSharedSystem();
-
- // set up the predefined attributes
- info.attrFactory().predefined().setWholeArchive();
- info.attrFactory().predefined().setDynamic();
-
-}
-
-X86ELFSectLinker::~X86ELFSectLinker()
-{
-}
-
diff --git a/lib/Target/X86/X86ELFSectLinker.h b/lib/Target/X86/X86ELFSectLinker.h
deleted file mode 100644
index 5e7abfd..0000000
--- a/lib/Target/X86/X86ELFSectLinker.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- X86ELFSectLinker.h -------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef X86_ELFSECTLINKER_H
-#define X86_ELFSECTLINKER_H
-#ifdef ENABLE_UNITTEST
-#include <gtest.h>
-#endif
-#include <mcld/CodeGen/SectLinker.h>
-
-namespace mcld
-{
-
-/** \class X86ELFSectLinker
- * \brief X86ELFSectLinker sets up the environment for linking.
- *
- * \see
- */
-class X86ELFSectLinker : public SectLinker
-{
-public:
- X86ELFSectLinker(SectLinkerOption &pOption,
- mcld::TargetLDBackend &pLDBackend);
-
- ~X86ELFSectLinker();
-};
-
-} // namespace of mcld
-
-#endif
-
diff --git a/lib/Target/X86/X86Emulation.cpp b/lib/Target/X86/X86Emulation.cpp
new file mode 100644
index 0000000..74b7e47
--- /dev/null
+++ b/lib/Target/X86/X86Emulation.cpp
@@ -0,0 +1,60 @@
+//===- X86Emulation.cpp ---------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "X86.h"
+#include <mcld/LinkerConfig.h>
+#include <mcld/Target/ELFEmulation.h>
+#include <mcld/Support/TargetRegistry.h>
+
+namespace mcld {
+
+static bool MCLDEmulateX86ELF(LinkerConfig& pConfig)
+{
+ if (!MCLDEmulateELF(pConfig))
+ return false;
+
+ // set up target-dependent constraints of attributes
+ pConfig.attribute().constraint().enableWholeArchive();
+ pConfig.attribute().constraint().enableAsNeeded();
+ pConfig.attribute().constraint().setSharedSystem();
+
+ // set up the predefined attributes
+ pConfig.attribute().predefined().unsetWholeArchive();
+ pConfig.attribute().predefined().unsetAsNeeded();
+ pConfig.attribute().predefined().setDynamic();
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// emulateX86LD - the help function to emulate X86 ld
+//===----------------------------------------------------------------------===//
+bool emulateX86LD(const std::string& pTriple, LinkerConfig& pConfig)
+{
+ llvm::Triple theTriple(pTriple);
+ if (theTriple.isOSDarwin()) {
+ assert(0 && "MachO linker has not supported yet");
+ return false;
+ }
+ if (theTriple.isOSWindows()) {
+ assert(0 && "COFF linker has not supported yet");
+ return false;
+ }
+
+ return MCLDEmulateX86ELF(pConfig);
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// X86Emulation
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeX86Emulation() {
+ // Register the emulation
+ mcld::TargetRegistry::RegisterEmulation(mcld::TheX86Target, mcld::emulateX86LD);
+}
+
diff --git a/lib/Target/X86/X86GOT.cpp b/lib/Target/X86/X86GOT.cpp
index 518cc36..ae28ea7 100644
--- a/lib/Target/X86/X86GOT.cpp
+++ b/lib/Target/X86/X86GOT.cpp
@@ -8,13 +8,8 @@
//===----------------------------------------------------------------------===//
#include "X86GOT.h"
-#include <new>
-
-#include <llvm/Support/Casting.h>
-
#include <mcld/LD/LDFileFormat.h>
#include <mcld/LD/SectionData.h>
-#include <mcld/Support/MsgHandling.h>
namespace {
const size_t X86GOTEntrySize = 4;
@@ -25,9 +20,8 @@
//===----------------------------------------------------------------------===//
// X86GOT
//===----------------------------------------------------------------------===//
-X86GOT::X86GOT(LDSection& pSection, SectionData& pSectionData)
- : GOT(pSection, pSectionData, X86GOTEntrySize),
- m_GOTIterator(), m_fIsVisit(false)
+X86GOT::X86GOT(LDSection& pSection)
+ : GOT(pSection, X86GOTEntrySize)
{
}
@@ -35,63 +29,3 @@
{
}
-void X86GOT::reserveEntry(size_t pNum)
-{
- GOTEntry* Entry = 0;
-
- for (size_t i = 0; i < pNum; i++) {
- Entry = new (std::nothrow) GOTEntry(0, X86GOTEntrySize,
- &m_SectionData);
-
- if (!Entry)
- fatal(diag::fail_allocate_memory_got);
-
- m_Section.setSize(m_Section.size() + X86GOTEntrySize);
- }
-}
-
-
-GOTEntry* X86GOT::getEntry(const ResolveInfo& pInfo, bool& pExist)
-{
- // first time visit this function, set m_GOTIterator
- if(!m_fIsVisit) {
- assert( !m_SectionData.getFragmentList().empty() &&
- "DynRelSection contains no entries.");
- m_GOTIterator = m_SectionData.getFragmentList().begin();
- m_fIsVisit = true;
- }
-
-
- GOTEntry *&Entry = m_GOTMap[&pInfo];
- pExist = 1;
-
- if (!Entry) {
- pExist = 0;
- assert(m_GOTIterator != m_SectionData.getFragmentList().end()
- && "The number of GOT Entries and ResolveInfo doesn't match!");
- Entry = llvm::cast<GOTEntry>(&(*m_GOTIterator));
- ++m_GOTIterator;
- }
- return Entry;
-}
-
-X86GOT::iterator X86GOT::begin()
-{
- return m_SectionData.getFragmentList().begin();
-}
-
-X86GOT::const_iterator X86GOT::begin() const
-{
- return m_SectionData.getFragmentList().begin();
-}
-
-X86GOT::iterator X86GOT::end()
-{
- return m_SectionData.getFragmentList().end();
-}
-
-X86GOT::const_iterator X86GOT::end() const
-{
- return m_SectionData.getFragmentList().end();
-}
-
diff --git a/lib/Target/X86/X86GOT.h b/lib/Target/X86/X86GOT.h
index 91cc3e8..a027dc7 100644
--- a/lib/Target/X86/X86GOT.h
+++ b/lib/Target/X86/X86GOT.h
@@ -12,14 +12,12 @@
#include <gtest.h>
#endif
-#include "X86PLT.h"
-
#include <mcld/Target/GOT.h>
-#include <mcld/LD/SectionData.h>
-namespace mcld
-{
+namespace mcld {
+
class LDSection;
+class SectionData;
/** \class X86GOT
* \brief X86 Global Offset Table.
@@ -27,38 +25,10 @@
class X86GOT : public GOT
{
- typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
-
public:
- typedef SectionData::iterator iterator;
- typedef SectionData::const_iterator const_iterator;
-
-public:
- X86GOT(LDSection& pSection, SectionData& pSectionData);
+ X86GOT(LDSection& pSection);
~X86GOT();
-
- //Reserve general GOT entries.
- void reserveEntry(size_t pNum = 1);
-
- GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist);
-
- iterator begin();
-
- const_iterator begin() const;
-
- iterator end();
-
- const_iterator end() const;
-
-private:
- /// m_GOTIterator - point to the first valid entry in GOT list
- iterator m_GOTIterator;
-
- /// m_fIsVisit - first time visit the function getEntry() or not
- bool m_fIsVisit;
-
- SymbolIndexMapType m_GOTMap;
};
} // namespace of mcld
diff --git a/lib/Target/X86/X86GOTPLT.cpp b/lib/Target/X86/X86GOTPLT.cpp
index 49f3449..b4e0ffe 100644
--- a/lib/Target/X86/X86GOTPLT.cpp
+++ b/lib/Target/X86/X86GOTPLT.cpp
@@ -6,13 +6,14 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#include "X86GOTPLT.h"
+#include "X86PLT.h"
#include <new>
#include <llvm/Support/Casting.h>
+#include <mcld/LD/LDSection.h>
#include <mcld/LD/LDFileFormat.h>
#include <mcld/Support/MsgHandling.h>
@@ -25,114 +26,45 @@
//===----------------------------------------------------------------------===//
// X86GOTPLT
//===----------------------------------------------------------------------===//
-X86GOTPLT::X86GOTPLT(LDSection& pSection, SectionData& pSectionData)
- : GOT(pSection, pSectionData, X86GOTPLTEntrySize), m_GOTPLTIterator()
+X86GOTPLT::X86GOTPLT(LDSection& pSection)
+ : GOT(pSection, X86GOTPLTEntrySize)
{
- GOTEntry* Entry = 0;
+ // Create GOT0 entries
+ reserve(X86GOTPLT0Num);
- // Create GOT0 entries.
- for (size_t i = 0; i < X86GOTPLT0Num; i++) {
- Entry = new (std::nothrow) GOTEntry(0, X86GOTPLTEntrySize,
- &m_SectionData);
-
- if (!Entry)
- fatal(diag::fail_allocate_memory_got);
-
- m_Section.setSize(m_Section.size() + X86GOTPLTEntrySize);
+ // Skip GOT0 entries
+ for (size_t i = 0; i < X86GOTPLT0Num; ++i) {
+ consume();
}
-
- // Skip GOT0 entries.
- iterator it = m_SectionData.begin();
-
- for (size_t i = 1; i < X86GOTPLT0Num; ++i) {
- assert((it != m_SectionData.end()) &&
- "Generation of GOT0 entries is incomplete!");
-
- ++it;
- }
-
- m_GOTPLTIterator = it;
}
X86GOTPLT::~X86GOTPLT()
{
}
-X86GOTPLT::iterator X86GOTPLT::begin()
+bool X86GOTPLT::hasGOT1() const
{
- return m_SectionData.begin();
-}
-
-X86GOTPLT::const_iterator X86GOTPLT::begin() const
-{
- return m_SectionData.begin();
-}
-
-X86GOTPLT::iterator X86GOTPLT::end()
-{
- return m_SectionData.end();
-}
-
-X86GOTPLT::const_iterator X86GOTPLT::end() const
-{
- return m_SectionData.end();
+ return (m_SectionData->size() > X86GOTPLT0Num);
}
void X86GOTPLT::applyGOT0(uint64_t pAddress)
{
- llvm::cast<GOTEntry>
- (*(m_SectionData.getFragmentList().begin())).setContent(pAddress);
+ llvm::cast<Entry>
+ (*(m_SectionData->getFragmentList().begin())).setContent(pAddress);
}
-void X86GOTPLT::reserveEntry(size_t pNum)
-{
- GOTEntry* got_entry = NULL;
- for (size_t i = 0; i < pNum; ++i) {
- got_entry = new GOTEntry(0, getEntrySize(),&(getSectionData()));
- if (!got_entry)
- fatal(diag::fail_allocate_memory_got);
-
- m_Section.setSize(m_Section.size() + getEntrySize());
- }
-}
-
-void X86GOTPLT::applyAllGOTPLT(uint64_t pPLTBase,
- unsigned int pPLT0Size,
- unsigned int pPLT1Size)
+void X86GOTPLT::applyAllGOTPLT(const X86PLT& pPLT)
{
iterator it = begin();
// skip GOT0
for (size_t i = 0; i < X86GOTPLT0Num; ++i)
++it;
// address of corresponding plt entry
- uint64_t plt_addr = pPLTBase + pPLT0Size;
+ uint64_t plt_addr = pPLT.addr() + pPLT.getPLT0Size();
for (; it != end() ; ++it) {
- llvm::cast<GOTEntry>(*it).setContent(plt_addr + 6);
- plt_addr += pPLT1Size;
+ llvm::cast<Entry>(*it).setContent(plt_addr + 6);
+ plt_addr += pPLT.getPLT1Size();
}
}
-GOTEntry*& X86GOTPLT::lookupGOTPLTMap(const ResolveInfo& pSymbol)
-{
- return m_GOTPLTMap[&pSymbol];
-}
-
-GOTEntry* X86GOTPLT::getEntry(const ResolveInfo& pInfo, bool& pExist)
-{
- GOTEntry *&Entry = m_GOTPLTMap[&pInfo];
- pExist = 1;
-
- if (!Entry) {
- pExist = 0;
-
- ++m_GOTPLTIterator;
- assert(m_GOTPLTIterator != m_SectionData.getFragmentList().end()
- && "The number of GOT Entries and ResolveInfo doesn't match!");
-
- Entry = llvm::cast<GOTEntry>(&(*m_GOTPLTIterator));
- }
-
- return Entry;
-}
-
} //end mcld namespace
diff --git a/lib/Target/X86/X86GOTPLT.h b/lib/Target/X86/X86GOTPLT.h
index 7ca695b..b2fa65a 100644
--- a/lib/Target/X86/X86GOTPLT.h
+++ b/lib/Target/X86/X86GOTPLT.h
@@ -15,10 +15,10 @@
#include <llvm/ADT/DenseMap.h>
#include <mcld/Target/GOT.h>
-#include <mcld/LD/SectionData.h>
-namespace mcld
-{
+namespace mcld {
+
+class X86PLT;
class LDSection;
const unsigned int X86GOTPLT0Num = 3;
@@ -28,44 +28,17 @@
*/
class X86GOTPLT : public GOT
{
- typedef llvm::DenseMap<const ResolveInfo*, GOTEntry*> SymbolIndexMapType;
-
public:
- typedef SectionData::iterator iterator;
- typedef SectionData::const_iterator const_iterator;
-
-public:
- X86GOTPLT(LDSection &pSection, SectionData& pSectionData);
+ X86GOTPLT(LDSection &pSection);
~X86GOTPLT();
- iterator begin();
+ // hasGOT1 - return if this section has any GOT1 entry
+ bool hasGOT1() const;
- const_iterator begin() const;
-
- iterator end();
-
- const_iterator end() const;
-
-// For GOT0
-public:
void applyGOT0(uint64_t pAddress);
-// For GOTPLT
-public:
- void reserveEntry(size_t pNum = 1);
-
- GOTEntry* getEntry(const ResolveInfo& pSymbol, bool& pExist);
-
- void applyAllGOTPLT(uint64_t pPLTBase,
- unsigned int pPLT0Size,
- unsigned int pPLT1Size);
-
- GOTEntry*& lookupGOTPLTMap(const ResolveInfo& pSymbol);
-
-private:
- iterator m_GOTPLTIterator;
- SymbolIndexMapType m_GOTPLTMap;
+ void applyAllGOTPLT(const X86PLT& pPLT);
};
} // namespace of mcld
diff --git a/lib/Target/X86/X86LDBackend.cpp b/lib/Target/X86/X86LDBackend.cpp
index d02e621..987daec 100644
--- a/lib/Target/X86/X86LDBackend.cpp
+++ b/lib/Target/X86/X86LDBackend.cpp
@@ -6,7 +6,6 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-
#include "X86.h"
#include "X86ELFDynamic.h"
#include "X86LDBackend.h"
@@ -15,22 +14,26 @@
#include <llvm/ADT/Triple.h>
#include <llvm/Support/Casting.h>
-#include <mcld/LD/SectionMap.h>
-#include <mcld/LD/FillFragment.h>
-#include <mcld/LD/RegionFragment.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLDOutput.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/Fragment/FillFragment.h>
+#include <mcld/Fragment/RegionFragment.h>
+#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Support/TargetRegistry.h>
+#include <mcld/Object/ObjectBuilder.h>
#include <cstring>
using namespace mcld;
-X86GNULDBackend::X86GNULDBackend()
- : m_pRelocFactory(NULL),
+//===----------------------------------------------------------------------===//
+// X86GNULDBackend
+//===----------------------------------------------------------------------===//
+X86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig)
+ : GNULDBackend(pConfig),
+ m_pRelocFactory(NULL),
m_pGOT(NULL),
m_pPLT(NULL),
m_pGOTPLT(NULL),
@@ -42,20 +45,13 @@
X86GNULDBackend::~X86GNULDBackend()
{
- if (NULL != m_pRelocFactory)
- delete m_pRelocFactory;
- if (NULL != m_pGOT)
- delete m_pGOT;
- if (NULL != m_pPLT)
- delete m_pPLT;
- if (NULL != m_pGOTPLT)
- delete m_pGOTPLT;
- if (NULL !=m_pRelDyn)
- delete m_pRelDyn;
- if (NULL != m_pRelPLT)
- delete m_pRelPLT;
- if (NULL != m_pDynamic)
- delete m_pDynamic;
+ delete m_pRelocFactory;
+ delete m_pGOT;
+ delete m_pPLT;
+ delete m_pGOTPLT;
+ delete m_pRelDyn;
+ delete m_pRelPLT;
+ delete m_pDynamic;
}
RelocationFactory* X86GNULDBackend::getRelocFactory()
@@ -64,28 +60,47 @@
return m_pRelocFactory;
}
-bool X86GNULDBackend::initRelocFactory(const MCLinker& pLinker)
+bool X86GNULDBackend::initRelocFactory(const FragmentLinker& pLinker)
{
if (NULL == m_pRelocFactory) {
m_pRelocFactory = new X86RelocationFactory(1024, *this);
- m_pRelocFactory->setLayout(pLinker.getLayout());
+ m_pRelocFactory->setFragmentLinker(pLinker);
}
return true;
}
-void X86GNULDBackend::doPreLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker)
+void X86GNULDBackend::doPreLayout(FragmentLinker& pLinker)
{
- // when building shared object, the .got section is needed
- if (Output::DynObj == pOutput.type() && (NULL == m_pGOTPLT)) {
- createX86GOTPLT(pLinker, pOutput);
+ // set .got.plt size
+ // when building shared object, the .got section is must
+ if (LinkerConfig::Object != config().codeGenType()) {
+ if (LinkerConfig::DynObj == config().codeGenType() ||
+ m_pGOTPLT->hasGOT1() ||
+ NULL != m_pGOTSymbol) {
+ m_pGOTPLT->finalizeSectionSize();
+ defineGOTSymbol(pLinker);
+ }
+
+ // set .got size
+ if (!m_pGOT->empty())
+ m_pGOT->finalizeSectionSize();
+
+ // set .plt size
+ if (m_pPLT->hasPLT1())
+ m_pPLT->finalizeSectionSize();
+
+ // set .rel.dyn size
+ if (!m_pRelDyn->empty())
+ m_pRelDyn->finalizeSectionSize();
+
+ // set .rel.plt size
+ if (!m_pRelPLT->empty())
+ m_pRelPLT->finalizeSectionSize();
}
}
-void X86GNULDBackend::doPostLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker)
+void X86GNULDBackend::doPostLayout(Module& pModule,
+ FragmentLinker& pLinker)
{
}
@@ -107,26 +122,11 @@
return *m_pDynamic;
}
-void X86GNULDBackend::createX86GOT(MCLinker& pLinker, const Output& pOutput)
+void X86GNULDBackend::defineGOTSymbol(FragmentLinker& pLinker)
{
- // get .got LDSection and create SectionData
- ELFFileFormat* file_format = getOutputFormat(pOutput);
-
- LDSection& got = file_format->getGOT();
- m_pGOT = new X86GOT(got, pLinker.getOrCreateSectData(got));
-}
-
-void X86GNULDBackend::createX86GOTPLT(MCLinker& pLinker, const Output& pOutput)
-{
- // get .got.plt LDSection and create SectionData
- ELFFileFormat* file_format = getOutputFormat(pOutput);
-
- LDSection& gotplt = file_format->getGOTPLT();
- m_pGOTPLT = new X86GOTPLT(gotplt, pLinker.getOrCreateSectData(gotplt));
-
- // define symbol _GLOBAL_OFFSET_TABLE_ when .got.plt create
+ // define symbol _GLOBAL_OFFSET_TABLE_
if (m_pGOTSymbol != NULL) {
- pLinker.defineSymbol<MCLinker::Force, MCLinker::Unresolve>(
+ pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Unresolve>(
"_GLOBAL_OFFSET_TABLE_",
false,
ResolveInfo::Object,
@@ -134,12 +134,11 @@
ResolveInfo::Local,
0x0, // size
0x0, // value
- pLinker.getLayout().getFragmentRef(*(m_pGOTPLT->begin()),
- 0x0),
+ FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
ResolveInfo::Hidden);
}
else {
- m_pGOTSymbol = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+ m_pGOTSymbol = pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
"_GLOBAL_OFFSET_TABLE_",
false,
ResolveInfo::Object,
@@ -147,81 +146,43 @@
ResolveInfo::Local,
0x0, // size
0x0, // value
- pLinker.getLayout().getFragmentRef(*(m_pGOTPLT->begin()),
- 0x0),
+ FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
ResolveInfo::Hidden);
}
}
-void X86GNULDBackend::createX86PLTandRelPLT(MCLinker& pLinker,
- const Output& pOutput)
-{
- ELFFileFormat* file_format = getOutputFormat(pOutput);
-
- LDSection& plt = file_format->getPLT();
- LDSection& relplt = file_format->getRelPlt();
- assert(m_pGOTPLT != NULL);
- // create SectionData and X86PLT
- m_pPLT = new X86PLT(plt, pLinker.getOrCreateSectData(plt), *m_pGOTPLT, pOutput);
-
- // set info of .rel.plt to .plt
- relplt.setLink(&plt);
- // create SectionData and X86RelDynSection
- m_pRelPLT = new OutputRelocSection(relplt,
- pLinker.getOrCreateSectData(relplt),
- 8);
-}
-
-void X86GNULDBackend::createX86RelDyn(MCLinker& pLinker,
- const Output& pOutput)
-{
- // get .rel.dyn LDSection and create SectionData
- ELFFileFormat* file_format = getOutputFormat(pOutput);
-
- LDSection& reldyn = file_format->getRelDyn();
- // create SectionData and X86RelDynSection
- m_pRelDyn = new OutputRelocSection(reldyn,
- pLinker.getOrCreateSectData(reldyn),
- 8);
-}
-
void X86GNULDBackend::addCopyReloc(ResolveInfo& pSym)
{
- bool exist;
- Relocation& rel_entry = *m_pRelDyn->getEntry(pSym, false, exist);
+ Relocation& rel_entry = *m_pRelDyn->consumeEntry();
rel_entry.setType(llvm::ELF::R_386_COPY);
assert(pSym.outSymbol()->hasFragRef());
rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef());
rel_entry.setSymInfo(&pSym);
}
-LDSymbol& X86GNULDBackend::defineSymbolforCopyReloc(MCLinker& pLinker,
+/// defineSymbolforCopyReloc
+/// For a symbol needing copy relocation, define a copy symbol in the BSS
+/// section and all other reference to this symbol should refer to this
+/// copy.
+/// @note This is executed at `scan relocation' stage.
+LDSymbol& X86GNULDBackend::defineSymbolforCopyReloc(FragmentLinker& pLinker,
const ResolveInfo& pSym)
{
- // For a symbol needing copy relocation, define a copy symbol in the BSS
- // section and all other reference to this symbol should refer to this
- // copy.
-
// get or create corresponding BSS LDSection
LDSection* bss_sect_hdr = NULL;
- if (ResolveInfo::ThreadLocal == pSym.type()) {
- bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(
- ".tbss",
- LDFileFormat::BSS,
- llvm::ELF::SHT_NOBITS,
- llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
- }
- else {
- bss_sect_hdr = &pLinker.getOrCreateOutputSectHdr(".bss",
- LDFileFormat::BSS,
- llvm::ELF::SHT_NOBITS,
- llvm::ELF::SHF_WRITE | llvm::ELF::SHF_ALLOC);
- }
+ ELFFileFormat* file_format = getOutputFormat();
+ if (ResolveInfo::ThreadLocal == pSym.type())
+ bss_sect_hdr = &file_format->getTBSS();
+ else
+ bss_sect_hdr = &file_format->getBSS();
// get or create corresponding BSS SectionData
assert(NULL != bss_sect_hdr);
- SectionData& bss_section = pLinker.getOrCreateSectData(
- *bss_sect_hdr);
+ SectionData* bss_section = NULL;
+ if (bss_sect_hdr->hasSectionData())
+ bss_section = bss_sect_hdr->getSectionData();
+ else
+ bss_section = IRBuilder::CreateSectionData(*bss_sect_hdr);
// Determine the alignment by the symbol value
// FIXME: here we use the largest alignment
@@ -229,9 +190,9 @@
// allocate space in BSS for the copy symbol
Fragment* frag = new FillFragment(0x0, 1, pSym.size());
- uint64_t size = pLinker.getLayout().appendFragment(*frag,
- bss_section,
- addralign);
+ uint64_t size = ObjectBuilder::AppendFragment(*frag,
+ *bss_section,
+ addralign);
bss_sect_hdr->setSize(bss_sect_hdr->size() + size);
// change symbol binding to Global if it's a weak symbol
@@ -240,7 +201,8 @@
binding = ResolveInfo::Global;
// Define the copy symbol in the bss section and resolve it
- LDSymbol* cpy_sym = pLinker.defineSymbol<MCLinker::Force, MCLinker::Resolve>(
+ LDSymbol* cpy_sym =
+ pLinker.defineSymbol<FragmentLinker::Force, FragmentLinker::Resolve>(
pSym.name(),
false,
(ResolveInfo::Type)pSym.type(),
@@ -248,44 +210,29 @@
binding,
pSym.size(), // size
0x0, // value
- pLinker.getLayout().getFragmentRef(*frag, 0x0),
+ FragmentRef::Create(*frag, 0x0),
(ResolveInfo::Visibility)pSym.other());
return *cpy_sym;
}
-void X86GNULDBackend::updateAddend(Relocation& pReloc,
- const LDSymbol& pInputSym,
- const Layout& pLayout) const
-{
- // Update value keep in addend if we meet a section symbol
- if (pReloc.symInfo()->type() == ResolveInfo::Section) {
- pReloc.setAddend(pLayout.getOutputOffset(
- *pInputSym.fragRef()) + pReloc.addend());
- }
-}
-
void X86GNULDBackend::scanLocalReloc(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput)
+ FragmentLinker& pLinker,
+ Module& pModule,
+ const LDSection& pSection)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
- updateAddend(pReloc, pInputSym, pLinker.getLayout());
-
switch(pReloc.type()){
case llvm::ELF::R_386_32:
+ case llvm::ELF::R_386_16:
+ case llvm::ELF::R_386_8:
// If buiding PIC object (shared library or PIC executable),
// a dynamic relocations with RELATIVE type to this location is needed.
// Reserve an entry in .rel.dyn
- if (isOutputPIC(pOutput, pLDInfo)) {
- // create .rel.dyn section if not exist
- if (NULL == m_pRelDyn)
- createX86RelDyn(pLinker, pOutput);
+ if (pLinker.isOutputPIC()) {
m_pRelDyn->reserveEntry(*m_pRelocFactory);
// set Rel bit
rsym->setReserved(rsym->reserved() | ReserveRel);
@@ -294,12 +241,112 @@
case llvm::ELF::R_386_GOTOFF:
case llvm::ELF::R_386_GOTPC:
- // A GOT section is needed
- if (NULL == m_pGOT)
- createX86GOT(pLinker, pOutput);
+ // FIXME: A GOT section is needed
+ return;
+
+ case llvm::ELF::R_386_GOT32:
+ // Symbol needs GOT entry, reserve entry in .got
+ // return if we already create GOT for this symbol
+ if (rsym->reserved() & (ReserveGOT | GOTRel))
+ return;
+ // FIXME: check STT_GNU_IFUNC symbol
+ m_pGOT->reserve();
+ // If building shared object or the symbol is undefined, a dynamic
+ // relocation is needed to relocate this GOT entry. Reserve an
+ // entry in .rel.dyn
+ if (LinkerConfig::DynObj ==
+ config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
+ m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ // set GOTRel bit
+ rsym->setReserved(rsym->reserved() | GOTRel);
+ return;
+ }
+ // set GOT bit
+ rsym->setReserved(rsym->reserved() | ReserveGOT);
return;
case llvm::ELF::R_386_PC32:
+ case llvm::ELF::R_386_PC16:
+ case llvm::ELF::R_386_PC8:
+ return;
+
+ case llvm::ELF::R_386_TLS_GD: {
+ // FIXME: no linker optimization for TLS relocation
+ if (rsym->reserved() & GOTRel)
+ return;
+ m_pGOT->reserve(2);
+ // reserve an rel entry
+ m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ // set GOTRel bit
+ rsym->setReserved(rsym->reserved() | GOTRel);
+ // define the section symbol for .tdata or .tbss
+ // the target symbol of the created dynamic relocation should be the
+ // section symbol of the section which this symbol defined. so we
+ // need to define that section symbol here
+ ELFFileFormat* file_format = getOutputFormat();
+ const LDSection* sym_sect =
+ &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection();
+ if (&file_format->getTData() == sym_sect) {
+ if (NULL == f_pTDATA)
+ f_pTDATA = pModule.getSectionSymbolSet().get(*sym_sect);
+ }
+ else if (&file_format->getTBSS() == sym_sect || rsym->isCommon()) {
+ if (NULL == f_pTBSS)
+ f_pTBSS = pModule.getSectionSymbolSet().get(*sym_sect);
+ }
+ else
+ error(diag::invalid_tls) << rsym->name() << sym_sect->name();
+ return;
+ }
+
+ case llvm::ELF::R_386_TLS_LDM:
+ getTLSModuleID();
+ return;
+
+ case llvm::ELF::R_386_TLS_LDO_32:
+ return;
+
+ case llvm::ELF::R_386_TLS_IE:
+ setHasStaticTLS();
+ // if buildint shared object, a RELATIVE dynamic relocation is needed
+ if (LinkerConfig::DynObj == config().codeGenType()) {
+ m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ rsym->setReserved(rsym->reserved() | ReserveRel);
+ }
+ if (rsym->reserved() & GOTRel)
+ return;
+ // reserve got and dyn relocation entries for tp-relative offset
+ m_pGOT->reserve();
+ m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ // set GOTRel bit
+ rsym->setReserved(rsym->reserved() | GOTRel);
+ m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol());
+ return;
+
+ case llvm::ELF::R_386_TLS_GOTIE:
+ setHasStaticTLS();
+ if (rsym->reserved() & GOTRel)
+ return;
+ // reserve got and dyn relocation entries for tp-relative offset
+ m_pGOT->reserve();
+ m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ // set GOTRel bit
+ rsym->setReserved(rsym->reserved() | GOTRel);
+ m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol());
+ return;
+
+ case llvm::ELF::R_386_TLS_LE:
+ case llvm::ELF::R_386_TLS_LE_32:
+ setHasStaticTLS();
+ // if buildint shared object, a dynamic relocation is needed
+ if (LinkerConfig::DynObj == config().codeGenType()) {
+ m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ rsym->setReserved(rsym->reserved() | ReserveRel);
+ // the target symbol of the dynamic relocation is rsym, so we need to
+ // emit it into .dynsym
+ assert(NULL != rsym->outSymbol());
+ m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol());
+ }
return;
default:
@@ -310,47 +357,39 @@
}
void X86GNULDBackend::scanGlobalReloc(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput)
+ FragmentLinker& pLinker,
+ Module& pModule,
+ const LDSection& pSection)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
switch(pReloc.type()) {
case llvm::ELF::R_386_32:
+ case llvm::ELF::R_386_16:
+ case llvm::ELF::R_386_8:
// Absolute relocation type, symbol may needs PLT entry or
// dynamic relocation entry
- if (symbolNeedsPLT(*rsym, pLDInfo, pOutput)) {
+ if (symbolNeedsPLT(pLinker, *rsym)) {
// create plt for this symbol if it does not have one
if (!(rsym->reserved() & ReservePLT)){
- // Create .got section if it dosen't exist
- if (NULL == m_pGOTPLT)
- createX86GOTPLT(pLinker, pOutput);
- // create .plt and .rel.plt if not exist
- if (NULL == m_pPLT)
- createX86PLTandRelPLT(pLinker, pOutput);
// Symbol needs PLT entry, we need to reserve a PLT entry
// and the corresponding GOT and dynamic relocation entry
// in .got and .rel.plt. (GOT entry will be reserved simultaneously
// when calling X86PLT->reserveEntry())
m_pPLT->reserveEntry();
+ m_pGOTPLT->reserve();
m_pRelPLT->reserveEntry(*m_pRelocFactory);
// set PLT bit
rsym->setReserved(rsym->reserved() | ReservePLT);
}
}
- if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
- pLDInfo, pOutput, true)) {
+ if (symbolNeedsDynRel(pLinker, *rsym, (rsym->reserved() & ReservePLT),
+ true)) {
// symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
- // create .rel.dyn section if not exist
- if (NULL == m_pRelDyn)
- createX86RelDyn(pLinker, pOutput);
m_pRelDyn->reserveEntry(*m_pRelocFactory);
- if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
- pOutput)) {
+ if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
addCopyReloc(*cpy_sym.resolveInfo());
}
@@ -363,9 +402,7 @@
case llvm::ELF::R_386_GOTOFF:
case llvm::ELF::R_386_GOTPC: {
- // A GOT section is needed
- if (NULL == m_pGOT)
- createX86GOT(pLinker, pOutput);
+ // FIXME: A GOT section is needed
return;
}
@@ -376,24 +413,23 @@
if (rsym->reserved() & ReservePLT)
return;
+ // if the symbol's value can be decided at link time, then no need plt
+ if (symbolFinalValueIsKnown(pLinker, *rsym))
+ return;
+
// if symbol is defined in the ouput file and it's not
// preemptible, no need plt
if (rsym->isDefine() && !rsym->isDyn() &&
- !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) {
+ !isSymbolPreemptible(*rsym)) {
return;
}
- // Create .got section if it dosen't exist
- if (NULL == m_pGOTPLT)
- createX86GOTPLT(pLinker, pOutput);
- // create .plt and .rel.plt if not exist
- if (NULL == m_pPLT)
- createX86PLTandRelPLT(pLinker, pOutput);
// Symbol needs PLT entry, we need to reserve a PLT entry
// and the corresponding GOT and dynamic relocation entry
// in .got and .rel.plt. (GOT entry will be reserved simultaneously
// when calling X86PLT->reserveEntry())
m_pPLT->reserveEntry();
+ m_pGOTPLT->reserve();
m_pRelPLT->reserveEntry(*m_pRelocFactory);
// set PLT bit
rsym->setReserved(rsym->reserved() | ReservePLT);
@@ -404,16 +440,12 @@
// return if we already create GOT for this symbol
if (rsym->reserved() & (ReserveGOT | GOTRel))
return;
- if (NULL == m_pGOT)
- createX86GOT(pLinker, pOutput);
- m_pGOT->reserveEntry();
+ m_pGOT->reserve();
// If building shared object or the symbol is undefined, a dynamic
// relocation is needed to relocate this GOT entry. Reserve an
// entry in .rel.dyn
- if (Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) {
- // create .rel.dyn section if not exist
- if (NULL == m_pRelDyn)
- createX86RelDyn(pLinker, pOutput);
+ if (LinkerConfig::DynObj ==
+ config().codeGenType() || rsym->isUndef() || rsym->isDyn()) {
m_pRelDyn->reserveEntry(*m_pRelocFactory);
// set GOTRel bit
rsym->setReserved(rsym->reserved() | GOTRel);
@@ -424,37 +456,30 @@
return;
case llvm::ELF::R_386_PC32:
+ case llvm::ELF::R_386_PC16:
+ case llvm::ELF::R_386_PC8:
- if (symbolNeedsPLT(*rsym, pLDInfo, pOutput) &&
- pOutput.type() != Output::DynObj) {
+ if (symbolNeedsPLT(pLinker, *rsym) &&
+ LinkerConfig::DynObj != config().codeGenType()) {
// create plt for this symbol if it does not have one
if (!(rsym->reserved() & ReservePLT)){
- // Create .got section if it dosen't exist
- if (NULL == m_pGOTPLT)
- createX86GOTPLT(pLinker, pOutput);
- // create .plt and .rel.plt if not exist
- if (NULL == m_pPLT)
- createX86PLTandRelPLT(pLinker, pOutput);
// Symbol needs PLT entry, we need to reserve a PLT entry
// and the corresponding GOT and dynamic relocation entry
// in .got and .rel.plt. (GOT entry will be reserved simultaneously
// when calling X86PLT->reserveEntry())
m_pPLT->reserveEntry();
+ m_pGOTPLT->reserve();
m_pRelPLT->reserveEntry(*m_pRelocFactory);
// set PLT bit
rsym->setReserved(rsym->reserved() | ReservePLT);
}
}
- if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT),
- pLDInfo, pOutput, false)) {
+ if (symbolNeedsDynRel(pLinker, *rsym, (rsym->reserved() & ReservePLT),
+ false)) {
// symbol needs dynamic relocation entry, reserve an entry in .rel.dyn
- // create .rel.dyn section if not exist
- if (NULL == m_pRelDyn)
- createX86RelDyn(pLinker, pOutput);
m_pRelDyn->reserveEntry(*m_pRelocFactory);
- if (symbolNeedsCopyReloc(pLinker.getLayout(), pReloc, *rsym, pLDInfo,
- pOutput)) {
+ if (symbolNeedsCopyReloc(pLinker, pReloc, *rsym)) {
LDSymbol& cpy_sym = defineSymbolforCopyReloc(pLinker, *rsym);
addCopyReloc(*cpy_sym.resolveInfo());
}
@@ -464,6 +489,63 @@
}
}
return;
+
+ case llvm::ELF::R_386_TLS_GD: {
+ // FIXME: no linker optimization for TLS relocation
+ if (rsym->reserved() & GOTRel)
+ return;
+ // reserve two pairs of got entry and dynamic relocation
+ m_pGOT->reserve(2);
+ m_pRelDyn->reserveEntry(*m_pRelocFactory, 2);
+ // set GOTRel bit
+ rsym->setReserved(rsym->reserved() | GOTRel);
+ return;
+ }
+
+ case llvm::ELF::R_386_TLS_LDM:
+ getTLSModuleID();
+ return;
+
+ case llvm::ELF::R_386_TLS_LDO_32:
+ return;
+
+ case llvm::ELF::R_386_TLS_IE:
+ setHasStaticTLS();
+ // if buildint shared object, a RELATIVE dynamic relocation is needed
+ if (LinkerConfig::DynObj == config().codeGenType()) {
+ m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ rsym->setReserved(rsym->reserved() | ReserveRel);
+ }
+ if (rsym->reserved() & GOTRel)
+ return;
+ // reserve got and dyn relocation entries for tp-relative offset
+ m_pGOT->reserve();
+ m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ // set GOTRel bit
+ rsym->setReserved(rsym->reserved() | GOTRel);
+ return;
+
+ case llvm::ELF::R_386_TLS_GOTIE:
+ setHasStaticTLS();
+ if (rsym->reserved() & GOTRel)
+ return;
+ // reserve got and dyn relocation entries for tp-relative offset
+ m_pGOT->reserve();
+ m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ // set GOTRel bit
+ rsym->setReserved(rsym->reserved() | GOTRel);
+ return;
+
+ case llvm::ELF::R_386_TLS_LE:
+ case llvm::ELF::R_386_TLS_LE_32:
+ setHasStaticTLS();
+ // if buildint shared object, a dynamic relocation is needed
+ if (LinkerConfig::DynObj == config().codeGenType()) {
+ m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ rsym->setReserved(rsym->reserved() | ReserveRel);
+ }
+ return;
+
default: {
fatal(diag::unsupported_relocation) << (int)pReloc.type()
<< "mclinker@googlegroups.com";
@@ -473,56 +555,45 @@
}
void X86GNULDBackend::scanRelocation(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput,
+ FragmentLinker& pLinker,
+ Module& pModule,
const LDSection& pSection)
{
+ if (LinkerConfig::Object == config().codeGenType())
+ return;
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
- assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation");
+ assert(NULL != rsym &&
+ "ResolveInfo of relocation not set while scanRelocation");
- assert(NULL != pSection.getLink());
- if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) {
- if (rsym->isLocal()) {
- updateAddend(pReloc, pInputSym, pLinker.getLayout());
- }
+ pReloc.updateAddend();
+ if (0 == (pSection.flag() & llvm::ELF::SHF_ALLOC))
return;
- }
- // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation
+ // Scan relocation type to determine if the GOT/PLT/Dynamic Relocation
// entries should be created.
- // FIXME: Below judgements concern only .so is generated as output
- // FIXME: Below judgements concren nothing about TLS related relocation
+ if (rsym->isLocal()) // rsym is local
+ scanLocalReloc(pReloc, pLinker, pModule, pSection);
+ else // rsym is external
+ scanGlobalReloc(pReloc, pLinker, pModule, pSection);
- // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got.plt
- // section is needed
- if (NULL == m_pGOTPLT && NULL != m_pGOTSymbol) {
- if (rsym == m_pGOTSymbol->resolveInfo()) {
- createX86GOTPLT(pLinker, pOutput);
- }
+ // check if we shoule issue undefined reference for the relocation target
+ // symbol
+ if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak())
+ fatal(diag::undefined_reference) << rsym->name();
+
+ if ((rsym->reserved() & ReserveRel) != 0x0) {
+ // set hasTextRelSection if needed
+ checkAndSetHasTextRel(pSection);
}
-
- // rsym is local
- if (rsym->isLocal())
- scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput);
-
- // rsym is external
- else
- scanGlobalReloc(pReloc, pInputSym ,pLinker, pLDInfo, pOutput);
-
}
-uint64_t X86GNULDBackend::emitSectionData(const Output& pOutput,
- const LDSection& pSection,
- const MCLDInfo& pInfo,
- const Layout& pLayout,
+uint64_t X86GNULDBackend::emitSectionData(const LDSection& pSection,
MemoryRegion& pRegion) const
{
assert(pRegion.size() && "Size of MemoryRegion is zero!");
- const ELFFileFormat* FileFormat = getOutputFormat(pOutput);
+ const ELFFileFormat* FileFormat = getOutputFormat();
assert(FileFormat &&
"ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!");
@@ -536,7 +607,6 @@
m_pPLT->applyPLT0();
m_pPLT->applyPLT1();
-
X86PLT::iterator it = m_pPLT->begin();
unsigned int plt0_size = llvm::cast<X86PLT0>((*it)).getEntrySize();
@@ -560,12 +630,12 @@
uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
- GOTEntry* got = 0;
+ GOT::Entry* got = 0;
EntrySize = m_pGOT->getEntrySize();
for (X86GOT::iterator it = m_pGOT->begin(),
ie = m_pGOT->end(); it != ie; ++it, ++buffer) {
- got = &(llvm::cast<GOTEntry>((*it)));
+ got = &(llvm::cast<GOT::Entry>((*it)));
*buffer = static_cast<uint32_t>(got->getContent());
RegionSize += EntrySize;
}
@@ -574,15 +644,16 @@
else if (&pSection == &(FileFormat->getGOTPLT())) {
assert(m_pGOTPLT && "emitSectionData failed, m_pGOTPLT is NULL!");
m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr());
+ m_pGOTPLT->applyAllGOTPLT(*m_pPLT);
uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer());
- GOTEntry* got = 0;
+ GOT::Entry* got = 0;
EntrySize = m_pGOTPLT->getEntrySize();
for (X86GOTPLT::iterator it = m_pGOTPLT->begin(),
ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) {
- got = &(llvm::cast<GOTEntry>((*it)));
+ got = &(llvm::cast<GOT::Entry>((*it)));
*buffer = static_cast<uint32_t>(got->getContent());
RegionSize += EntrySize;
}
@@ -595,6 +666,7 @@
}
return RegionSize;
}
+
uint32_t X86GNULDBackend::machine() const
{
return llvm::ELF::EM_386;
@@ -648,6 +720,27 @@
return *m_pRelDyn;
}
+// Create a GOT entry for the TLS module index
+GOT::Entry& X86GNULDBackend::getTLSModuleID()
+{
+ static GOT::Entry* got_entry = NULL;
+ if (NULL != got_entry)
+ return *got_entry;
+
+ // Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM
+ m_pGOT->reserve(2);
+ got_entry = m_pGOT->consume();
+ m_pGOT->consume()->setContent(0x0);
+
+ m_pRelDyn->reserveEntry(*m_pRelocFactory);
+ Relocation* rel_entry = m_pRelDyn->consumeEntry();
+ rel_entry->setType(llvm::ELF::R_386_TLS_DTPMOD32);
+ rel_entry->targetRef().assign(*got_entry, 0x0);
+ rel_entry->setSymInfo(NULL);
+
+ return *got_entry;
+}
+
OutputRelocSection& X86GNULDBackend::getRelPLT()
{
assert(NULL != m_pRelPLT && ".rel.plt section not exist");
@@ -661,20 +754,18 @@
}
unsigned int
-X86GNULDBackend::getTargetSectionOrder(const Output& pOutput,
- const LDSection& pSectHdr,
- const MCLDInfo& pInfo) const
+X86GNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
{
- const ELFFileFormat* file_format = getOutputFormat(pOutput);
+ const ELFFileFormat* file_format = getOutputFormat();
if (&pSectHdr == &file_format->getGOT()) {
- if (pInfo.options().hasNow())
+ if (config().options().hasNow())
return SHO_RELRO;
return SHO_RELRO_LAST;
}
if (&pSectHdr == &file_format->getGOTPLT()) {
- if (pInfo.options().hasNow())
+ if (config().options().hasNow())
return SHO_RELRO;
return SHO_NON_RELRO_FIRST;
}
@@ -690,47 +781,80 @@
return 32;
}
-bool X86GNULDBackend::initTargetSectionMap(SectionMap& pSectionMap)
+void X86GNULDBackend::initTargetSections(Module& pModule, ObjectBuilder& pBuilder)
{
- return true;
+ if (LinkerConfig::Object != config().codeGenType()) {
+ ELFFileFormat* file_format = getOutputFormat();
+ // initialize .got
+ LDSection& got = file_format->getGOT();
+ m_pGOT = new X86GOT(got);
+
+ // initialize .got.plt
+ LDSection& gotplt = file_format->getGOTPLT();
+ m_pGOTPLT = new X86GOTPLT(gotplt);
+
+ // initialize .plt
+ LDSection& plt = file_format->getPLT();
+ m_pPLT = new X86PLT(plt,
+ *m_pGOTPLT,
+ config());
+
+ // initialize .rel.plt
+ LDSection& relplt = file_format->getRelPlt();
+ relplt.setLink(&plt);
+ m_pRelPLT = new OutputRelocSection(pModule,
+ relplt,
+ getRelEntrySize());
+ // initialize .rel.dyn
+ LDSection& reldyn = file_format->getRelDyn();
+ m_pRelDyn = new OutputRelocSection(pModule,
+ reldyn,
+ getRelEntrySize());
+ }
}
-void X86GNULDBackend::initTargetSections(MCLinker& pLinker)
+void X86GNULDBackend::initTargetSymbols(FragmentLinker& pLinker)
{
-}
-
-void X86GNULDBackend::initTargetSymbols(MCLinker& pLinker, const Output& pOutput)
-{
- // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
- // same name in input
- m_pGOTSymbol = pLinker.defineSymbol<MCLinker::AsRefered, MCLinker::Resolve>(
- "_GLOBAL_OFFSET_TABLE_",
- false,
- ResolveInfo::Object,
- ResolveInfo::Define,
- ResolveInfo::Local,
- 0x0, // size
- 0x0, // value
- NULL, // FragRef
- ResolveInfo::Hidden);
+ if (LinkerConfig::Object != config().codeGenType()) {
+ // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
+ // same name in input
+ m_pGOTSymbol =
+ pLinker.defineSymbol<FragmentLinker::AsRefered,
+ FragmentLinker::Resolve>("_GLOBAL_OFFSET_TABLE_",
+ false,
+ ResolveInfo::Object,
+ ResolveInfo::Define,
+ ResolveInfo::Local,
+ 0x0, // size
+ 0x0, // value
+ FragmentRef::Null(), // FragRef
+ ResolveInfo::Hidden);
+ }
}
/// finalizeSymbol - finalize the symbol value
-bool X86GNULDBackend::finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput)
+bool X86GNULDBackend::finalizeTargetSymbols(FragmentLinker& pLinker)
{
return true;
}
+/// doCreateProgramHdrs - backend can implement this function to create the
+/// target-dependent segments
+void X86GNULDBackend::doCreateProgramHdrs(Module& pModule,
+ const FragmentLinker& pLinker)
+{
+ // TODO
+}
+
namespace mcld {
//===----------------------------------------------------------------------===//
/// createX86LDBackend - the help funtion to create corresponding X86LDBackend
///
TargetLDBackend* createX86LDBackend(const llvm::Target& pTarget,
- const std::string& pTriple)
+ const LinkerConfig& pConfig)
{
- Triple theTriple(pTriple);
- if (theTriple.isOSDarwin()) {
+ if (pConfig.triple().isOSDarwin()) {
assert(0 && "MachO linker is not supported yet");
/**
return new X86MachOLDBackend(createX86MachOArchiveReader,
@@ -738,7 +862,7 @@
createX86MachOObjectWriter);
**/
}
- if (theTriple.isOSWindows()) {
+ if (pConfig.triple().isOSWindows()) {
assert(0 && "COFF linker is not supported yet");
/**
return new X86COFFLDBackend(createX86COFFArchiveReader,
@@ -746,14 +870,15 @@
createX86COFFObjectWriter);
**/
}
- return new X86GNULDBackend();
+ return new X86GNULDBackend(pConfig);
}
} // namespace of mcld
-//=============================
+//===----------------------------------------------------------------------===//
// Force static initialization.
-extern "C" void LLVMInitializeX86LDBackend() {
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeX86LDBackend() {
// Register the linker backend
mcld::TargetRegistry::RegisterTargetLDBackend(TheX86Target, createX86LDBackend);
}
diff --git a/lib/Target/X86/X86LDBackend.h b/lib/Target/X86/X86LDBackend.h
index 7264c40..fb3aa6b 100644
--- a/lib/Target/X86/X86LDBackend.h
+++ b/lib/Target/X86/X86LDBackend.h
@@ -19,6 +19,8 @@
namespace mcld {
+class LinkerConfig;
+
//===----------------------------------------------------------------------===//
/// X86GNULDBackend - linker backend of X86 target of GNU ELF format
///
@@ -68,7 +70,8 @@
PLTandRel = 9
};
- X86GNULDBackend();
+public:
+ X86GNULDBackend(const LinkerConfig& pConfig);
~X86GNULDBackend();
@@ -91,17 +94,15 @@
const X86PLT& getPLT() const;
+ GOT::Entry& getTLSModuleID();
+
unsigned int bitclass() const;
/// preLayout - Backend can do any needed modification before layout
- void doPreLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker);
+ void doPreLayout(FragmentLinker& pLinker);
/// postLayout -Backend can do any needed modification after layout
- void doPostLayout(const Output& pOutput,
- const MCLDInfo& pInfo,
- MCLinker& pLinker);
+ void doPostLayout(Module& pModule, FragmentLinker& pLinker);
/// dynamic - the dynamic section of the target machine.
/// Use co-variant return type to return its own dynamic section.
@@ -122,16 +123,11 @@
/// - backend can maintain its own map<LDSection, table> to get the table
/// from given LDSection.
///
- /// @param pOutput - the output file
/// @param pSection - the given LDSection
- /// @param pInfo - all options in the command line.
/// @param pLayout - for comouting the size of fragment
/// @param pRegion - the region to write out data
/// @return the size of the table in the file.
- uint64_t emitSectionData(const Output& pOutput,
- const LDSection& pSection,
- const MCLDInfo& pInfo,
- const Layout& pLayout,
+ uint64_t emitSectionData(const LDSection& pSection,
MemoryRegion& pRegion) const;
/// OSABI - the value of e_ident[EI_OSABI]
@@ -152,15 +148,12 @@
uint64_t defaultTextSegmentAddr() const
{ return 0x08048000; }
- /// initTargetSectionMap - initialize target dependent section mapping
- bool initTargetSectionMap(SectionMap& pSectionMap);
-
// initRelocFactory - create and initialize RelocationFactory
- bool initRelocFactory(const MCLinker& pLinker);
+ bool initRelocFactory(const FragmentLinker& pLinker);
- void initTargetSections(MCLinker& pLinker);
+ void initTargetSections(Module& pModule, ObjectBuilder& pBuilder);
- void initTargetSymbols(MCLinker& pLinker, const Output& pOutput);
+ void initTargetSymbols(FragmentLinker& pLinker);
/// scanRelocation - determine the empty entries are needed or not and create
/// the empty entries if needed.
@@ -169,10 +162,8 @@
/// - PLT entry (for .plt section)
/// - dynamin relocation entries (for .rel.plt and .rel.dyn sections)
void scanRelocation(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput,
+ FragmentLinker& pLinker,
+ Module& pModule,
const LDSection& pSection);
OutputRelocSection& getRelDyn();
@@ -184,25 +175,21 @@
const OutputRelocSection& getRelPLT() const;
/// getTargetSectionOrder - compute the layout order of X86 target sections
- unsigned int getTargetSectionOrder(const Output& pOutput,
- const LDSection& pSectHdr,
- const MCLDInfo& pInfo) const;
+ unsigned int getTargetSectionOrder(const LDSection& pSectHdr) const;
/// finalizeTargetSymbols - finalize the symbol value
- bool finalizeTargetSymbols(MCLinker& pLinker, const Output& pOutput);
+ bool finalizeTargetSymbols(FragmentLinker& pLinker);
private:
void scanLocalReloc(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput);
+ FragmentLinker& pLinker,
+ Module& pModule,
+ const LDSection& pSection);
void scanGlobalReloc(Relocation& pReloc,
- const LDSymbol& pInputSym,
- MCLinker& pLinker,
- const MCLDInfo& pLDInfo,
- const Output& pOutput);
+ FragmentLinker& pLinker,
+ Module& pModule,
+ const LDSection& pSection);
/// addCopyReloc - add a copy relocation into .rel.dyn for pSym
/// @param pSym - A resolved copy symbol that defined in BSS section
@@ -211,17 +198,23 @@
/// defineSymbolforCopyReloc - allocate a space in BSS section and
/// and force define the copy of pSym to BSS section
/// @return the output LDSymbol of the copy symbol
- LDSymbol& defineSymbolforCopyReloc(MCLinker& pLinker,
+ LDSymbol& defineSymbolforCopyReloc(FragmentLinker& pLinker,
const ResolveInfo& pSym);
- void updateAddend(Relocation& pReloc,
- const LDSymbol& pInputSym,
- const Layout& pLayout) const;
+ void defineGOTSymbol(FragmentLinker& pLinker);
- void createX86GOT(MCLinker& pLinker, const Output& pOutput);
- void createX86GOTPLT(MCLinker& pLinker, const Output& pOutput);
- void createX86PLTandRelPLT(MCLinker& pLinker, const Output& pOutput);
- void createX86RelDyn(MCLinker& pLinker, const Output& pOutput);
+ /// getRelEntrySize - the size in BYTE of rel type relocation
+ size_t getRelEntrySize()
+ { return 8; }
+
+ /// getRelEntrySize - the size in BYTE of rela type relocation
+ size_t getRelaEntrySize()
+ { return 12; }
+
+ /// doCreateProgramHdrs - backend can implement this function to create the
+ /// target-dependent segments
+ virtual void doCreateProgramHdrs(Module& pModule,
+ const FragmentLinker& pLinker);
private:
RelocationFactory* m_pRelocFactory;
diff --git a/lib/Target/X86/X86MCLinker.cpp b/lib/Target/X86/X86MCLinker.cpp
new file mode 100644
index 0000000..e55add3
--- /dev/null
+++ b/lib/Target/X86/X86MCLinker.cpp
@@ -0,0 +1,53 @@
+//===- X86MCLinker.cpp ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "X86.h"
+#include "X86ELFMCLinker.h"
+#include <mcld/Module.h>
+#include <mcld/Support/TargetRegistry.h>
+#include <llvm/ADT/Triple.h>
+
+using namespace mcld;
+
+namespace mcld {
+
+//===----------------------------------------------------------------------===//
+/// createX86MCLinker - the help funtion to create corresponding X86MCLinker
+//===----------------------------------------------------------------------===//
+MCLinker* createX86MCLinker(const std::string &pTriple,
+ LinkerConfig& pConfig,
+ mcld::Module& pModule,
+ MemoryArea& pOutput)
+{
+ Triple theTriple(pTriple);
+ if (theTriple.isOSDarwin()) {
+ assert(0 && "MachO linker has not supported yet");
+ return NULL;
+ }
+ if (theTriple.isOSWindows()) {
+ assert(0 && "COFF linker has not supported yet");
+ return NULL;
+ }
+
+ if (theTriple.isArch32Bit())
+ return new X86ELFMCLinker(pConfig, pModule, pOutput);
+
+ assert(0 && "X86_64 has not supported yet");
+ return NULL;
+}
+
+} // namespace of mcld
+
+//===----------------------------------------------------------------------===//
+// X86MCLinker
+//===----------------------------------------------------------------------===//
+extern "C" void MCLDInitializeX86MCLinker() {
+ // Register the linker frontend
+ mcld::TargetRegistry::RegisterMCLinker(TheX86Target, createX86MCLinker);
+}
+
diff --git a/lib/Target/X86/X86PLT.cpp b/lib/Target/X86/X86PLT.cpp
index cbdb568..5b5ac58 100644
--- a/lib/Target/X86/X86PLT.cpp
+++ b/lib/Target/X86/X86PLT.cpp
@@ -9,12 +9,11 @@
#include "X86GOTPLT.h"
#include "X86PLT.h"
-#include <new>
-
#include <llvm/Support/ELF.h>
#include <llvm/Support/Casting.h>
-#include <mcld/MC/MCLDOutput.h>
+#include <mcld/LD/LDSection.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/Support/MsgHandling.h>
//===----------------------------------------------------------------------===//
@@ -50,26 +49,26 @@
namespace mcld {
-X86PLT0::X86PLT0(SectionData* pParent, unsigned int pSize)
- : PLTEntry(pSize, pParent) { }
+X86PLT0::X86PLT0(SectionData& pParent, unsigned int pSize)
+ : PLT::Entry(pSize, pParent) { }
-X86PLT1::X86PLT1(SectionData* pParent, unsigned int pSize)
- : PLTEntry(pSize, pParent) { }
+X86PLT1::X86PLT1(SectionData& pParent, unsigned int pSize)
+ : PLT::Entry(pSize, pParent) { }
//===----------------------------------------------------------------------===//
// X86PLT
//===----------------------------------------------------------------------===//
X86PLT::X86PLT(LDSection& pSection,
- SectionData& pSectionData,
X86GOTPLT &pGOTPLT,
- const Output& pOutput)
- : PLT(pSection, pSectionData),
+ const LinkerConfig& pConfig)
+ : PLT(pSection),
m_GOTPLT(pGOTPLT),
- m_PLTEntryIterator(),
- m_Output(pOutput)
+ m_Config(pConfig)
{
- assert (Output::DynObj == pOutput.type() || Output::Exec == pOutput.type());
- if (Output::DynObj == pOutput.type()) {
+ assert(LinkerConfig::DynObj == m_Config.codeGenType() ||
+ LinkerConfig::Exec == m_Config.codeGenType());
+
+ if (LinkerConfig::DynObj == m_Config.codeGenType()) {
m_PLT0 = x86_dyn_plt0;
m_PLT1 = x86_dyn_plt1;
m_PLT0Size = sizeof (x86_dyn_plt0);
@@ -81,62 +80,71 @@
m_PLT0Size = sizeof (x86_exec_plt0);
m_PLT1Size = sizeof (x86_exec_plt1);
}
- X86PLT0* plt0_entry = new X86PLT0(&m_SectionData, m_PLT0Size);
+ new X86PLT0(*m_SectionData, m_PLT0Size);
- m_Section.setSize(m_Section.size() + plt0_entry->getEntrySize());
-
- m_PLTEntryIterator = pSectionData.begin();
+ m_Last = m_SectionData->begin();
}
X86PLT::~X86PLT()
{
}
+void X86PLT::finalizeSectionSize()
+{
+ uint64_t size = 0;
+ // plt0 size
+ size = getPLT0()->getEntrySize();
+
+ // get first plt1 entry
+ X86PLT::iterator it = begin();
+ ++it;
+ if (end() != it) {
+ // plt1 size
+ X86PLT1* plt1 = &(llvm::cast<X86PLT1>(*it));
+ size += (m_SectionData->size() - 1) * plt1->getEntrySize();
+ }
+ m_Section.setSize(size);
+
+ uint32_t offset = 0;
+ SectionData::iterator frag, fragEnd = m_SectionData->end();
+ for (frag = m_SectionData->begin(); frag != fragEnd; ++frag) {
+ frag->setOffset(offset);
+ offset += frag->size();
+ }
+}
+
+bool X86PLT::hasPLT1() const
+{
+ return (m_SectionData->size() > 1);
+}
+
void X86PLT::reserveEntry(size_t pNum)
{
X86PLT1* plt1_entry = 0;
for (size_t i = 0; i < pNum; ++i) {
- plt1_entry = new (std::nothrow) X86PLT1(&m_SectionData, m_PLT1Size);
+ plt1_entry = new (std::nothrow) X86PLT1(*m_SectionData, m_PLT1Size);
if (!plt1_entry)
fatal(diag::fail_allocate_memory_plt);
-
- m_Section.setSize(m_Section.size() + plt1_entry->getEntrySize());
-
- // reserve corresponding entry in .got.plt
- m_GOTPLT.reserveEntry(pNum);
}
}
-PLTEntry* X86PLT::getPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
+PLT::Entry* X86PLT::consume()
{
- X86PLT1 *&PLTEntry = m_PLTEntryMap[&pSymbol];
-
- pExist = 1;
-
- if (!PLTEntry) {
- pExist = 0;
-
- // This will skip PLT0.
- ++m_PLTEntryIterator;
- assert(m_PLTEntryIterator != m_SectionData.end() &&
- "The number of PLT Entries and ResolveInfo doesn't match");
- PLTEntry = llvm::cast<X86PLT1>(&(*m_PLTEntryIterator));
- }
- return PLTEntry;
+ // This will skip PLT0.
+ ++m_Last;
+ assert(m_Last != m_SectionData->end() &&
+ "The number of PLT Entries and ResolveInfo doesn't match");
+ return llvm::cast<X86PLT1>(&(*m_Last));
}
-GOTEntry* X86PLT::getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist)
+X86PLT0* X86PLT::getPLT0() const
{
- return m_GOTPLT.getEntry(pSymbol, pExist);
-}
-X86PLT0* X86PLT::getPLT0() const {
+ iterator first = m_SectionData->getFragmentList().begin();
- iterator first = m_SectionData.getFragmentList().begin();
-
- assert(first != m_SectionData.getFragmentList().end() &&
+ assert(first != m_SectionData->getFragmentList().end() &&
"FragmentList is empty, getPLT0 failed!");
X86PLT0* plt0 = &(llvm::cast<X86PLT0>(*first));
@@ -145,14 +153,9 @@
}
// FIXME: It only works on little endian machine.
-void X86PLT::applyPLT0() {
-
- iterator first = m_SectionData.getFragmentList().begin();
-
- assert(first != m_SectionData.getFragmentList().end() &&
- "FragmentList is empty, applyPLT0 failed!");
-
- X86PLT0* plt0 = &(llvm::cast<X86PLT0>(*first));
+void X86PLT::applyPLT0()
+{
+ X86PLT0* plt0 = getPLT0();
unsigned char* data = 0;
data = static_cast<unsigned char*>(malloc(plt0->getEntrySize()));
@@ -163,34 +166,30 @@
memcpy(data, m_PLT0, plt0->getEntrySize());
if (m_PLT0 == x86_exec_plt0) {
- uint64_t got_base = m_GOTPLT.getSection().addr();
- assert(got_base && ".got base address is NULL!");
uint32_t *offset = reinterpret_cast<uint32_t*>(data + 2);
- *offset = got_base + 4;
+ *offset = m_GOTPLT.addr() + 4;
offset = reinterpret_cast<uint32_t*>(data + 8);
- *offset = got_base + 8;
+ *offset = m_GOTPLT.addr() + 8;
}
plt0->setContent(data);
}
// FIXME: It only works on little endian machine.
-void X86PLT::applyPLT1() {
+void X86PLT::applyPLT1()
+{
+ assert(m_Section.addr() && ".plt base address is NULL!");
- uint64_t plt_base = m_Section.addr();
- assert(plt_base && ".plt base address is NULL!");
-
- uint64_t got_base = m_GOTPLT.getSection().addr();
- assert(got_base && ".got base address is NULL!");
-
- X86PLT::iterator it = m_SectionData.begin();
- X86PLT::iterator ie = m_SectionData.end();
+ X86PLT::iterator it = m_SectionData->begin();
+ X86PLT::iterator ie = m_SectionData->end();
assert(it != ie && "FragmentList is empty, applyPLT1 failed!");
uint64_t GOTEntrySize = m_GOTPLT.getEntrySize();
// Skip GOT0
uint64_t GOTEntryOffset = GOTEntrySize * X86GOTPLT0Num;
+ if (LinkerConfig::Exec == m_Config.codeGenType())
+ GOTEntryOffset += m_GOTPLT.addr();
//skip PLT0
uint64_t PLTEntryOffset = m_PLT0Size;
@@ -213,12 +212,7 @@
uint32_t* offset;
offset = reinterpret_cast<uint32_t*>(data + 2);
- if (m_Output.type() == Output::DynObj) {
- *offset = GOTEntryOffset;
- } else {
- // Exec
- *offset = got_base + GOTEntryOffset;
- }
+ *offset = GOTEntryOffset;
GOTEntryOffset += GOTEntrySize;
offset = reinterpret_cast<uint32_t*>(data + 7);
@@ -232,9 +226,6 @@
plt1->setContent(data);
++it;
}
-
- // apply .got.plt
- m_GOTPLT.applyAllGOTPLT(plt_base, m_PLT0Size, m_PLT1Size);
}
} // end namespace mcld
diff --git a/lib/Target/X86/X86PLT.h b/lib/Target/X86/X86PLT.h
index 1669a49..5e8b45f 100644
--- a/lib/Target/X86/X86PLT.h
+++ b/lib/Target/X86/X86PLT.h
@@ -9,27 +9,24 @@
#ifndef MCLD_TARGET_X86_PLT_H
#define MCLD_TARGET_X86_PLT_H
-#include <llvm/ADT/DenseMap.h>
-
#include <mcld/Target/PLT.h>
-#include <mcld/LD/SectionData.h>
namespace mcld {
class X86GOTPLT;
class GOTEntry;
-class Output;
+class LinkerConfig;
-class X86PLT0 : public PLTEntry
+class X86PLT0 : public PLT::Entry
{
public:
- X86PLT0(SectionData* pParent, unsigned int pSize);
+ X86PLT0(SectionData& pParent, unsigned int pSize);
};
-class X86PLT1 : public PLTEntry
+class X86PLT1 : public PLT::Entry
{
public:
- X86PLT1(SectionData* pParent, unsigned int pSize);
+ X86PLT1(SectionData& pParent, unsigned int pSize);
};
/** \class X86PLT
@@ -37,60 +34,44 @@
*/
class X86PLT : public PLT
{
- typedef llvm::DenseMap<const ResolveInfo*, X86PLT1*> SymbolIndexType;
-
-public:
- typedef SectionData::iterator iterator;
- typedef SectionData::const_iterator const_iterator;
-
public:
X86PLT(LDSection& pSection,
- SectionData& pSectionData,
X86GOTPLT& pGOTPLT,
- const Output& pOutput);
+ const LinkerConfig& pConfig);
~X86PLT();
-// Override virtual function.
-public:
+ // finalizeSectionSize - set LDSection size
+ void finalizeSectionSize();
- // reserveEntry is X86GOT friend function.
+ // hasPLT1 - return if this PLT has any PLT1 entry
+ bool hasPLT1() const;
+
void reserveEntry(size_t pNum = 1) ;
- PLTEntry* getPLTEntry(const ResolveInfo& pSymbol, bool& pExist) ;
-
- GOTEntry* getGOTPLTEntry(const ResolveInfo& pSymbol, bool& pExist);
-
-public:
-
- iterator begin() { return m_SectionData.begin(); }
-
- const_iterator begin() const { return m_SectionData.begin(); }
-
- iterator end() { return m_SectionData.end(); }
-
- const_iterator end() const { return m_SectionData.end(); }
-
- X86PLT0* getPLT0() const;
+ PLT::Entry* consume();
void applyPLT0();
void applyPLT1();
+ unsigned int getPLT0Size() const { return m_PLT0Size; }
+ unsigned int getPLT1Size() const { return m_PLT1Size; }
+
+private:
+ X86PLT0* getPLT0() const;
+
private:
X86GOTPLT& m_GOTPLT;
- // Used by getEntry() for mapping a ResolveInfo
- // instance to a PLT1 Entry.
- iterator m_PLTEntryIterator;
-
- SymbolIndexType m_PLTEntryMap;
+ // the last consumed entry.
+ SectionData::iterator m_Last;
const uint8_t *m_PLT0;
const uint8_t *m_PLT1;
unsigned int m_PLT0Size;
unsigned int m_PLT1Size;
- const Output& m_Output;
+ const LinkerConfig& m_Config;
};
} // namespace of mcld
diff --git a/lib/Target/X86/X86RelocationFactory.cpp b/lib/Target/X86/X86RelocationFactory.cpp
index f603b6e..d7cfe09 100644
--- a/lib/Target/X86/X86RelocationFactory.cpp
+++ b/lib/Target/X86/X86RelocationFactory.cpp
@@ -10,8 +10,8 @@
#include <llvm/ADT/Twine.h>
#include <llvm/Support/DataTypes.h>
#include <llvm/Support/ELF.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/LD/Layout.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/Support/MsgHandling.h>
#include "X86RelocationFactory.h"
@@ -27,7 +27,6 @@
/// the prototype of applying function
typedef RelocationFactory::Result
(*ApplyFunctionType)(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
X86RelocationFactory& pParent);
// the table entry of applying functions
@@ -57,19 +56,16 @@
}
RelocationFactory::Result
-X86RelocationFactory::applyRelocation(Relocation& pRelocation,
- const MCLDInfo& pLDInfo)
+X86RelocationFactory::applyRelocation(Relocation& pRelocation)
{
Relocation::Type type = pRelocation.type();
if (type >= sizeof (ApplyFunctions) / sizeof (ApplyFunctions[0]) ) {
- fatal(diag::unknown_relocation) << (int)type <<
- pRelocation.symInfo()->name();
return Unknown;
}
// apply the relocation
- return ApplyFunctions[type].func(pRelocation, pLDInfo, *this);
+ return ApplyFunctions[type].func(pRelocation, *this);
}
const char* X86RelocationFactory::getName(Relocation::Type pType) const
@@ -81,119 +77,137 @@
// Relocation helper function
//===--------------------------------------------------------------------===//
-// Check if symbol can use relocation R_386_RELATIVE
+/// helper_DynRel - Get an relocation entry in .rel.dyn
+static
+Relocation& helper_DynRel(ResolveInfo* pSym,
+ Fragment& pFrag,
+ uint64_t pOffset,
+ X86RelocationFactory::Type pType,
+ X86RelocationFactory& pParent)
+{
+ X86GNULDBackend& ld_backend = pParent.getTarget();
+ Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
+ rel_entry.setType(pType);
+ rel_entry.targetRef().assign(pFrag, pOffset);
+ if (pType == llvm::ELF::R_386_RELATIVE || NULL == pSym)
+ rel_entry.setSymInfo(0);
+ else
+ rel_entry.setSymInfo(pSym);
+
+ return rel_entry;
+}
+
+
+/// helper_use_relative_reloc - Check if symbol can use relocation
+/// R_386_RELATIVE
static bool
helper_use_relative_reloc(const ResolveInfo& pSym,
- const MCLDInfo& pLDInfo,
const X86RelocationFactory& pFactory)
{
// if symbol is dynamic or undefine or preemptible
if (pSym.isDyn() ||
- pSym.isUndef() ||
- pFactory.getTarget().isSymbolPreemptible(pSym, pLDInfo, pLDInfo.output()))
+ pSym.isUndef() ||
+ pFactory.getTarget().isSymbolPreemptible(pSym))
return false;
return true;
}
static
-GOTEntry& helper_get_GOT_and_init(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
- X86RelocationFactory& pParent)
+GOT::Entry& helper_get_GOT_and_init(Relocation& pReloc,
+ X86RelocationFactory& pParent)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
X86GNULDBackend& ld_backend = pParent.getTarget();
- bool exist;
- GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist);
- if (!exist) {
- // If we first get this GOT entry, we should initialize it.
- if (rsym->reserved() & X86GNULDBackend::ReserveGOT) {
- // No corresponding dynamic relocation, initialize to the symbol value.
- got_entry.setContent(pReloc.symValue());
- }
- else if (rsym->reserved() & X86GNULDBackend::GOTRel) {
- // Initialize corresponding dynamic relocation.
- Relocation& rel_entry =
- *ld_backend.getRelDyn().getEntry(*rsym, true, exist);
- assert(!exist && "GOT entry not exist, but DynRel entry exist!");
- if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
- // Initialize got entry to target symbol address
- got_entry.setContent(pReloc.symValue());
- rel_entry.setType(llvm::ELF::R_386_RELATIVE);
- rel_entry.setSymInfo(0);
- }
- else {
- got_entry.setContent(0);
- rel_entry.setType(llvm::ELF::R_386_GLOB_DAT);
- rel_entry.setSymInfo(rsym);
- }
- rel_entry.targetRef().assign(got_entry);
+ GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+ if (NULL != got_entry)
+ return *got_entry;
+
+ // not found
+ got_entry = ld_backend.getGOT().consume();
+ pParent.getSymGOTMap().record(*rsym, *got_entry);
+
+ // If we first get this GOT entry, we should initialize it.
+ if (rsym->reserved() & X86GNULDBackend::ReserveGOT) {
+ // No corresponding dynamic relocation, initialize to the symbol value.
+ got_entry->setContent(pReloc.symValue());
+ }
+ else if (rsym->reserved() & X86GNULDBackend::GOTRel) {
+ // Initialize got_entry content and the corresponding dynamic relocation.
+ if (helper_use_relative_reloc(*rsym, pParent)) {
+ helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_RELATIVE, pParent);
+ got_entry->setContent(pReloc.symValue());
}
else {
- fatal(diag::reserve_entry_number_mismatch_got);
+ helper_DynRel(rsym, *got_entry, 0x0, llvm::ELF::R_386_GLOB_DAT, pParent);
+ got_entry->setContent(0);
}
}
- return got_entry;
+ else {
+ fatal(diag::reserve_entry_number_mismatch_got);
+ }
+ return *got_entry;
}
static
X86RelocationFactory::Address helper_GOT_ORG(X86RelocationFactory& pParent)
{
- return pParent.getTarget().getGOTPLT().getSection().addr();
+ return pParent.getTarget().getGOTPLT().addr();
}
static
X86RelocationFactory::Address helper_GOT(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
X86RelocationFactory& pParent)
{
- GOTEntry& got_entry = helper_get_GOT_and_init(pReloc, pLDInfo, pParent);
- X86RelocationFactory::Address got_addr =
- pParent.getTarget().getGOT().getSection().addr();
- return got_addr + pParent.getLayout().getOutputOffset(got_entry);
+ GOT::Entry& got_entry = helper_get_GOT_and_init(pReloc, pParent);
+ X86RelocationFactory::Address got_addr = pParent.getTarget().getGOT().addr();
+ return got_addr + got_entry.getOffset();
}
static
-PLTEntry& helper_get_PLT_and_init(Relocation& pReloc,
- X86RelocationFactory& pParent)
+PLT::Entry& helper_get_PLT_and_init(Relocation& pReloc,
+ X86RelocationFactory& pParent)
{
// rsym - The relocation target symbol
ResolveInfo* rsym = pReloc.symInfo();
X86GNULDBackend& ld_backend = pParent.getTarget();
- bool exist;
- PLTEntry& plt_entry = *ld_backend.getPLT().getPLTEntry(*rsym, exist);
- if (!exist) {
- // If we first get this PLT entry, we should initialize it.
- if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
- GOTEntry& gotplt_entry =
- *ld_backend.getPLT().getGOTPLTEntry(*rsym, exist);
- // Initialize corresponding dynamic relocation.
- Relocation& rel_entry =
- *ld_backend.getRelPLT().getEntry(*rsym, true, exist);
- assert(!exist && "PLT entry not exist, but DynRel entry exist!");
- rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT);
- rel_entry.targetRef().assign(gotplt_entry);
- rel_entry.setSymInfo(rsym);
- }
- else {
- fatal(diag::reserve_entry_number_mismatch_plt);
- }
- }
- return plt_entry;
-}
+ PLT::Entry* plt_entry = pParent.getSymPLTMap().lookUp(*rsym);
+ if (NULL != plt_entry)
+ return *plt_entry;
+ // not found
+ plt_entry = ld_backend.getPLT().consume();
+ pParent.getSymPLTMap().record(*rsym, *plt_entry);
+ // If we first get this PLT entry, we should initialize it.
+ if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
+ GOT::Entry* gotplt_entry = pParent.getSymGOTPLTMap().lookUp(*rsym);
+ assert(NULL == gotplt_entry && "PLT entry not exist, but DynRel entry exist!");
+ gotplt_entry = ld_backend.getGOTPLT().consume();
+ pParent.getSymGOTPLTMap().record(*rsym, *gotplt_entry);
+ // init the corresponding rel entry in .rel.plt
+ Relocation& rel_entry = *ld_backend.getRelPLT().consumeEntry();
+ rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT);
+ rel_entry.targetRef().assign(*gotplt_entry);
+ rel_entry.setSymInfo(rsym);
+ }
+ else {
+ fatal(diag::reserve_entry_number_mismatch_plt);
+ }
+
+ return *plt_entry;
+}
static
X86RelocationFactory::Address helper_PLT_ORG(X86RelocationFactory& pParent)
{
- return pParent.getTarget().getPLT().getSection().addr();
+ return pParent.getTarget().getPLT().addr();
}
@@ -201,31 +215,8 @@
X86RelocationFactory::Address helper_PLT(Relocation& pReloc,
X86RelocationFactory& pParent)
{
- PLTEntry& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
- return helper_PLT_ORG(pParent) + pParent.getLayout().getOutputOffset(plt_entry);
-}
-
-// Get an relocation entry in .rel.dyn and set its type to pType,
-// its FragmentRef to pReloc->targetFrag() and its ResolveInfo to pReloc->symInfo()
-static
-void helper_DynRel(Relocation& pReloc,
- X86RelocationFactory::Type pType,
- X86RelocationFactory& pParent)
-{
- // rsym - The relocation target symbol
- ResolveInfo* rsym = pReloc.symInfo();
- X86GNULDBackend& ld_backend = pParent.getTarget();
- bool exist;
-
- Relocation& rel_entry =
- *ld_backend.getRelDyn().getEntry(*rsym, false, exist);
- rel_entry.setType(pType);
- rel_entry.targetRef() = pReloc.targetRef();
-
- if (pType == llvm::ELF::R_386_RELATIVE)
- rel_entry.setSymInfo(0);
- else
- rel_entry.setSymInfo(rsym);
+ PLT::Entry& plt_entry = helper_get_PLT_and_init(pReloc, pParent);
+ return helper_PLT_ORG(pParent) + plt_entry.getOffset();
}
@@ -235,37 +226,46 @@
// R_386_NONE
X86RelocationFactory::Result none(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
X86RelocationFactory& pParent)
{
return X86RelocationFactory::OK;
}
// R_386_32: S + A
-X86RelocationFactory::Result abs32(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
- X86RelocationFactory& pParent)
+// R_386_16
+// R_386_8
+X86RelocationFactory::Result abs(Relocation& pReloc,
+ X86RelocationFactory& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
RelocationFactory::DWord S = pReloc.symValue();
bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel(
- *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT),
- pLDInfo, pLDInfo.output(), true);
+ pParent.getFragmentLinker(),
+ *rsym,
+ (rsym->reserved() & X86GNULDBackend::ReservePLT),
+ true);
- const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
- *(pReloc.targetRef().frag()));
- assert(NULL != target_sect);
+ LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
// If the flag of target section is not ALLOC, we will not scan this relocation
// but perform static relocation. (e.g., applying .debug section)
- if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+ if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
pReloc.target() = S + A;
return X86RelocationFactory::OK;
}
// A local symbol may need REL Type dynamic relocation
if (rsym->isLocal() && has_dyn_rel) {
- helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
+ if (llvm::ELF::R_386_32 == pReloc.type()) {
+ helper_DynRel(rsym, *pReloc.targetRef().frag(),
+ pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE,
+ pParent);
+ }
+ else {
+ // FIXME: check Section symbol
+ helper_DynRel(rsym, *pReloc.targetRef().frag(),
+ pReloc.targetRef().offset(), pReloc.type(), pParent);
+ }
pReloc.target() = S + A;
return X86RelocationFactory::OK;
}
@@ -274,17 +274,19 @@
if (!rsym->isLocal()) {
if (rsym->reserved() & X86GNULDBackend::ReservePLT) {
S = helper_PLT(pReloc, pParent);
- pReloc.target() = S + A;
}
// If we generate a dynamic relocation (except R_386_RELATIVE)
// for a place, we should not perform static relocation on it
// in order to keep the addend store in the place correct.
if (has_dyn_rel) {
- if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) {
- helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
+ if (llvm::ELF::R_386_32 == pReloc.type() &&
+ helper_use_relative_reloc(*rsym, pParent)) {
+ helper_DynRel(rsym, *pReloc.targetRef().frag(),
+ pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent);
}
else {
- helper_DynRel(pReloc, pReloc.type(), pParent);
+ helper_DynRel(rsym, *pReloc.targetRef().frag(),
+ pReloc.targetRef().offset(), pReloc.type(), pParent);
return X86RelocationFactory::OK;
}
}
@@ -296,21 +298,20 @@
}
// R_386_PC32: S + A - P
-X86RelocationFactory::Result rel32(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
- X86RelocationFactory& pParent)
+// R_386_PC16
+// R_386_PC8
+X86RelocationFactory::Result rel(Relocation& pReloc,
+ X86RelocationFactory& pParent)
{
ResolveInfo* rsym = pReloc.symInfo();
RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
RelocationFactory::DWord S = pReloc.symValue();
- RelocationFactory::DWord P = pReloc.place(pParent.getLayout());
+ RelocationFactory::DWord P = pReloc.place();
- const LDSection* target_sect = pParent.getLayout().getOutputLDSection(
- *(pReloc.targetRef().frag()));
- assert(NULL != target_sect);
+ LDSection& target_sect = pReloc.targetRef().frag()->getParent()->getSection();
// If the flag of target section is not ALLOC, we will not scan this relocation
// but perform static relocation. (e.g., applying .debug section)
- if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) {
+ if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect.flag())) {
pReloc.target() = S + A - P;
return X86RelocationFactory::OK;
}
@@ -322,13 +323,17 @@
pReloc.target() = S + A - P;
}
if (pParent.getTarget().symbolNeedsDynRel(
- *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT), pLDInfo,
- pLDInfo.output(), false)) {
- if (helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) {
- helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent);
+ pParent.getFragmentLinker(),
+ *rsym,
+ (rsym->reserved() & X86GNULDBackend::ReservePLT),
+ false)) {
+ if (helper_use_relative_reloc(*rsym, pParent) ) {
+ helper_DynRel(rsym, *pReloc.targetRef().frag(),
+ pReloc.targetRef().offset(), llvm::ELF::R_386_RELATIVE, pParent);
}
else {
- helper_DynRel(pReloc, pReloc.type(), pParent);
+ helper_DynRel(rsym, *pReloc.targetRef().frag(),
+ pReloc.targetRef().offset(), pReloc.type(), pParent);
return X86RelocationFactory::OK;
}
}
@@ -341,10 +346,9 @@
// R_386_GOTOFF: S + A - GOT_ORG
X86RelocationFactory::Result gotoff32(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
X86RelocationFactory& pParent)
{
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
X86RelocationFactory::Address S = pReloc.symValue();
@@ -354,27 +358,25 @@
// R_386_GOTPC: GOT_ORG + A - P
X86RelocationFactory::Result gotpc32(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
X86RelocationFactory& pParent)
{
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
// Apply relocation.
- pReloc.target() = GOT_ORG + A - pReloc.place(pParent.getLayout());
+ pReloc.target() = GOT_ORG + A - pReloc.place();
return X86RelocationFactory::OK;
}
// R_386_GOT32: GOT(S) + A - GOT_ORG
X86RelocationFactory::Result got32(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
X86RelocationFactory& pParent)
{
if (!(pReloc.symInfo()->reserved()
& (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) {
return X86RelocationFactory::BadReloc;
}
- X86RelocationFactory::Address GOT_S = helper_GOT(pReloc, pLDInfo, pParent);
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ X86RelocationFactory::Address GOT_S = helper_GOT(pReloc, pParent);
+ RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent);
// Apply relocation.
pReloc.target() = GOT_S + A - GOT_ORG;
@@ -383,7 +385,6 @@
// R_386_PLT32: PLT(S) + A - P
X86RelocationFactory::Result plt32(Relocation& pReloc,
- const MCLDInfo& pLDInfo,
X86RelocationFactory& pParent)
{
// PLT_S depends on if there is a PLT entry.
@@ -392,8 +393,204 @@
PLT_S = helper_PLT(pReloc, pParent);
else
PLT_S = pReloc.symValue();
- RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
- X86RelocationFactory::Address P = pReloc.place(pParent.getLayout());
+ RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ X86RelocationFactory::Address P = pReloc.place();
pReloc.target() = PLT_S + A - P;
return X86RelocationFactory::OK;
}
+
+// R_386_TLS_GD:
+X86RelocationFactory::Result tls_gd(Relocation& pReloc,
+ X86RelocationFactory& pParent)
+{
+ // global-dynamic
+ ResolveInfo* rsym = pReloc.symInfo();
+ // must reserve two pairs of got and dynamic relocation
+ if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
+ return X86RelocationFactory::BadReloc;
+ }
+
+ X86GNULDBackend& ld_backend = pParent.getTarget();
+ ELFFileFormat* file_format = pParent.getTarget().getOutputFormat();
+ // setup corresponding got and dynamic relocatio entries:
+ // get first got entry, if there is already a got entry for rsym, then apply
+ // this relocation to the got entry directly. If not, setup the corresponding
+ // got and dyn relocation entries
+ GOT::Entry* got_entry1 = pParent.getSymGOTMap().lookUp(*rsym);
+
+ if (NULL == got_entry1) {
+ // get and init two got entries if not exist
+ got_entry1 = ld_backend.getGOT().consume();
+ pParent.getSymGOTMap().record(*rsym, *got_entry1);
+ GOT::Entry* got_entry2 = ld_backend.getGOT().consume();
+ got_entry1->setContent(0x0);
+ got_entry2->setContent(0x0);
+ // setup dyn rel for get_entry1
+ Relocation& rel_entry1 = helper_DynRel(rsym, *got_entry1, 0x0,
+ llvm::ELF::R_386_TLS_DTPMOD32, pParent);
+ if (rsym->isLocal()) {
+ // for local symbol, set got_entry2 to symbol value
+ got_entry2->setContent(pReloc.symValue());
+
+ // for local tls symbol, add rel entry against the section symbol this
+ // symbol belong to (.tdata or .tbss)
+ const LDSection* sym_sect =
+ &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection();
+ ResolveInfo* sect_sym = NULL;
+ if (&file_format->getTData() == sym_sect)
+ sect_sym = pParent.getTarget().getTDATASymbol().resolveInfo();
+ else
+ sect_sym = pParent.getTarget().getTBSSSymbol().resolveInfo();
+ rel_entry1.setSymInfo(sect_sym);
+ }
+ else {
+ // for non-local symbol, add a pair of rel entries against this symbol
+ // for those two got entries
+ helper_DynRel(rsym, *got_entry2, 0x0,
+ llvm::ELF::R_386_TLS_DTPOFF32, pParent);
+ }
+ }
+
+ // perform relocation to the first got entry
+ RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ // GOT_OFF - the offset between the got_entry1 and _GLOBAL_OFFSET_TABLE (the
+ // .got.plt section)
+ X86RelocationFactory::Address GOT_OFF =
+ file_format->getGOT().addr() +
+ got_entry1->getOffset() -
+ file_format->getGOTPLT().addr();
+ pReloc.target() = GOT_OFF + A;
+ return X86RelocationFactory::OK;
+}
+
+// R_386_TLS_LDM
+X86RelocationFactory::Result tls_ldm(Relocation& pReloc,
+ X86RelocationFactory& pParent)
+{
+ // FIXME: no linker optimization for TLS relocation
+ const GOT::Entry& got_entry = pParent.getTarget().getTLSModuleID();
+
+ // All GOT offsets are relative to the end of the GOT.
+ X86RelocationFactory::SWord GOT_S = got_entry.getOffset() -
+ (pParent.getTarget().getGOTPLT().addr() -
+ pParent.getTarget().getGOT().addr());
+ RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ pReloc.target() = GOT_S + A;
+
+ return X86RelocationFactory::OK;
+}
+
+// R_386_TLS_LDO_32
+X86RelocationFactory::Result tls_ldo_32(Relocation& pReloc,
+ X86RelocationFactory& pParent)
+{
+ // FIXME: no linker optimization for TLS relocation
+ RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ X86RelocationFactory::Address S = pReloc.symValue();
+ pReloc.target() = S + A;
+ return X86RelocationFactory::OK;
+}
+
+// R_X86_TLS_IE
+X86RelocationFactory::Result tls_ie(Relocation& pReloc,
+ X86RelocationFactory& pParent)
+{
+ ResolveInfo* rsym = pReloc.symInfo();
+ if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
+ return X86RelocationFactory::BadReloc;
+ }
+
+ if (rsym->reserved() & X86GNULDBackend::ReserveRel) {
+ // when building shared object, set up a RELATIVE dynamic relocation
+ helper_DynRel(rsym, *pReloc.targetRef().frag(), pReloc.targetRef().offset(),
+ llvm::ELF::R_386_RELATIVE, pParent);
+ }
+
+ // set up the got and dynamic relocation entries if not exist
+ GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+ if (NULL == got_entry) {
+ // set got entry
+ X86GNULDBackend& ld_backend = pParent.getTarget();
+ got_entry = ld_backend.getGOT().consume();
+ pParent.getSymGOTMap().record(*rsym, *got_entry);
+ got_entry->setContent(0x0);
+ // set relocation entry
+ Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
+ rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
+ rel_entry.setSymInfo(rsym);
+ rel_entry.targetRef().assign(*got_entry);
+ }
+
+ // perform relocation to the absolute address of got_entry
+ X86RelocationFactory::Address GOT_S =
+ pParent.getTarget().getGOT().addr() + got_entry->getOffset();
+
+ RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ pReloc.target() = GOT_S + A;
+
+ return X86RelocationFactory::OK;
+}
+
+// R_386_TLS_GOTIE
+X86RelocationFactory::Result tls_gotie(Relocation& pReloc,
+ X86RelocationFactory& pParent)
+{
+ ResolveInfo* rsym = pReloc.symInfo();
+ if (!(rsym->reserved() & X86GNULDBackend::GOTRel)) {
+ return X86RelocationFactory::BadReloc;
+ }
+
+ // set up the got and dynamic relocation entries if not exist
+ GOT::Entry* got_entry = pParent.getSymGOTMap().lookUp(*rsym);
+ if (NULL == got_entry) {
+ // set got entry
+ X86GNULDBackend& ld_backend = pParent.getTarget();
+ got_entry = ld_backend.getGOT().consume();
+ pParent.getSymGOTMap().record(*rsym, *got_entry);
+ got_entry->setContent(0x0);
+ // set relocation entry
+ Relocation& rel_entry = *ld_backend.getRelDyn().consumeEntry();
+ rel_entry.setType(llvm::ELF::R_386_TLS_TPOFF);
+ rel_entry.setSymInfo(rsym);
+ rel_entry.targetRef().assign(*got_entry);
+ }
+
+ // All GOT offsets are relative to the end of the GOT.
+ X86RelocationFactory::SWord GOT_S = got_entry->getOffset() -
+ (pParent.getTarget().getGOTPLT().addr() - pParent.getTarget().getGOT().addr());
+ RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ pReloc.target() = GOT_S + A;
+
+ return X86RelocationFactory::OK;
+}
+
+// R_X86_TLS_LE
+X86RelocationFactory::Result tls_le(Relocation& pReloc,
+ X86RelocationFactory& pParent)
+{
+ ResolveInfo* rsym = pReloc.symInfo();
+ if (pReloc.symInfo()->reserved() & X86GNULDBackend::ReserveRel) {
+ helper_DynRel(rsym,
+ *pReloc.targetRef().frag(),
+ pReloc.targetRef().offset(),
+ llvm::ELF::R_386_TLS_TPOFF,
+ pParent);
+ return X86RelocationFactory::OK;
+ }
+
+ // perform static relocation
+ // get TLS segment
+ ELFSegment* tls_seg = pParent.getTarget().elfSegmentTable().find(
+ llvm::ELF::PT_TLS, llvm::ELF::PF_R, 0x0);
+ RelocationFactory::DWord A = pReloc.target() + pReloc.addend();
+ X86RelocationFactory::Address S = pReloc.symValue();
+ pReloc.target() = S + A - tls_seg->memsz();
+ return X86RelocationFactory::OK;
+}
+
+X86RelocationFactory::Result unsupport(Relocation& pReloc,
+ X86RelocationFactory& pParent)
+{
+ return X86RelocationFactory::Unsupport;
+}
+
diff --git a/lib/Target/X86/X86RelocationFactory.h b/lib/Target/X86/X86RelocationFactory.h
index 4b413d7..92119f1 100644
--- a/lib/Target/X86/X86RelocationFactory.h
+++ b/lib/Target/X86/X86RelocationFactory.h
@@ -14,10 +14,13 @@
#include <mcld/LD/RelocationFactory.h>
#include <mcld/Target/GOT.h>
+#include <mcld/Target/PLT.h>
+#include <mcld/Target/SymbolEntryMap.h>
#include "X86LDBackend.h"
-namespace mcld
-{
+namespace mcld {
+
+class ResolveInfo;
/** \class X86RelocationFactory
* \brief X86RelocationFactory creates and destroys the X86 relocations.
@@ -26,10 +29,14 @@
class X86RelocationFactory : public RelocationFactory
{
public:
+ typedef SymbolEntryMap<PLT::Entry> SymPLTMap;
+ typedef SymbolEntryMap<GOT::Entry> SymGOTMap;
+
+public:
X86RelocationFactory(size_t pNum, X86GNULDBackend& pParent);
~X86RelocationFactory();
- Result applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo);
+ Result applyRelocation(Relocation& pRelocation);
X86GNULDBackend& getTarget()
{ return m_Target; }
@@ -39,8 +46,20 @@
const char* getName(Relocation::Type pType) const;
+ const SymPLTMap& getSymPLTMap() const { return m_SymPLTMap; }
+ SymPLTMap& getSymPLTMap() { return m_SymPLTMap; }
+
+ const SymGOTMap& getSymGOTMap() const { return m_SymGOTMap; }
+ SymGOTMap& getSymGOTMap() { return m_SymGOTMap; }
+
+ const SymGOTMap& getSymGOTPLTMap() const { return m_SymGOTPLTMap; }
+ SymGOTMap& getSymGOTPLTMap() { return m_SymGOTPLTMap; }
+
private:
X86GNULDBackend& m_Target;
+ SymPLTMap m_SymPLTMap;
+ SymGOTMap m_SymGOTMap;
+ SymGOTMap m_SymGOTPLTMap;
};
} // namespace of mcld
diff --git a/lib/Target/X86/X86RelocationFunctions.h b/lib/Target/X86/X86RelocationFunctions.h
index 46d4f34..9b82739 100644
--- a/lib/Target/X86/X86RelocationFunctions.h
+++ b/lib/Target/X86/X86RelocationFunctions.h
@@ -9,23 +9,29 @@
#define DECL_X86_APPLY_RELOC_FUNC(Name) \
static X86RelocationFactory::Result Name (Relocation& pEntry, \
- const MCLDInfo& pLDInfo, \
X86RelocationFactory& pParent);
#define DECL_X86_APPLY_RELOC_FUNCS \
DECL_X86_APPLY_RELOC_FUNC(none) \
-DECL_X86_APPLY_RELOC_FUNC(abs32) \
-DECL_X86_APPLY_RELOC_FUNC(rel32) \
+DECL_X86_APPLY_RELOC_FUNC(abs) \
+DECL_X86_APPLY_RELOC_FUNC(rel) \
DECL_X86_APPLY_RELOC_FUNC(plt32) \
DECL_X86_APPLY_RELOC_FUNC(got32) \
-DECL_X86_APPLY_RELOC_FUNC(gotoff32) \
-DECL_X86_APPLY_RELOC_FUNC(gotpc32)
+DECL_X86_APPLY_RELOC_FUNC(gotoff32) \
+DECL_X86_APPLY_RELOC_FUNC(gotpc32) \
+DECL_X86_APPLY_RELOC_FUNC(tls_gd) \
+DECL_X86_APPLY_RELOC_FUNC(tls_ie) \
+DECL_X86_APPLY_RELOC_FUNC(tls_gotie) \
+DECL_X86_APPLY_RELOC_FUNC(tls_le) \
+DECL_X86_APPLY_RELOC_FUNC(tls_ldm) \
+DECL_X86_APPLY_RELOC_FUNC(tls_ldo_32) \
+DECL_X86_APPLY_RELOC_FUNC(unsupport)
#define DECL_X86_APPLY_RELOC_FUNC_PTRS \
{ &none, 0, "R_386_NONE" }, \
- { &abs32, 1, "R_386_32" }, \
- { &rel32, 2, "R_386_PC32" }, \
+ { &abs, 1, "R_386_32" }, \
+ { &rel, 2, "R_386_PC32" }, \
{ &got32, 3, "R_386_GOT32" }, \
{ &plt32, 4, "R_386_PLT32" }, \
{ &none, 5, "R_386_COPY" }, \
@@ -33,4 +39,37 @@
{ &none, 7, "R_386_JMP_SLOT" }, \
{ &none, 8, "R_386_RELATIVE" }, \
{ &gotoff32, 9, "R_386_GOTOFF" }, \
- { &gotpc32, 10, "R_386_GOTPC" }
+ { &gotpc32, 10, "R_386_GOTPC" }, \
+ { &unsupport, 11, "R_386_32PLT" }, \
+ { &unsupport, 12, "" }, \
+ { &unsupport, 13, "" }, \
+ { &unsupport, 14, "R_386_TLS_TPOFF" }, \
+ { &tls_ie, 15, "R_386_TLS_IE" }, \
+ { &tls_gotie, 16, "R_386_TLS_GOTIE" }, \
+ { &tls_le, 17, "R_386_TLS_LE" }, \
+ { &tls_gd, 18, "R_386_TLS_GD" }, \
+ { &tls_ldm, 19, "R_386_TLS_LDM" }, \
+ { &abs, 20, "R_386_16" }, \
+ { &rel, 21, "R_386_PC16" }, \
+ { &abs, 22, "R_386_8" }, \
+ { &rel, 23, "R_386_PC8" }, \
+ { &unsupport, 24, "R_386_TLS_GD_32" }, \
+ { &unsupport, 25, "R_386_TLS_GD_PUSH" }, \
+ { &unsupport, 26, "R_386_TLS_GD_CALL" }, \
+ { &unsupport, 27, "R_386_TLS_GD_POP" }, \
+ { &unsupport, 28, "R_386_TLS_LDM_32" }, \
+ { &unsupport, 29, "R_386_TLS_LDM_PUSH" }, \
+ { &unsupport, 30, "R_386_TLS_LDM_CALL" }, \
+ { &unsupport, 31, "R_386_TLS_LDM_POP" }, \
+ { &tls_ldo_32, 32, "R_386_TLS_LDO_32" }, \
+ { &unsupport, 33, "R_386_TLS_IE_32" }, \
+ { &unsupport, 34, "R_386_TLS_LE_32" }, \
+ { &unsupport, 35, "R_386_TLS_DTPMOD32" }, \
+ { &unsupport, 36, "R_386_TLS_DTPOFF32" }, \
+ { &unsupport, 37, "R_386_TLS_TPOFF32" }, \
+ { &unsupport, 38, "" }, \
+ { &unsupport, 39, "R_386_TLS_GOTDESC" }, \
+ { &unsupport, 40, "R_386_TLS_DESC_CALL" }, \
+ { &unsupport, 41, "R_386_TLS_DESC" }, \
+ { &unsupport, 42, "R_386_IRELATIVE" }, \
+ { &unsupport, 43, "R_386_NUM" }
diff --git a/lib/Target/X86/X86SectLinker.cpp b/lib/Target/X86/X86SectLinker.cpp
deleted file mode 100644
index 2954d1f..0000000
--- a/lib/Target/X86/X86SectLinker.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-//===- X86SectLinker.cpp --------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#include <llvm/ADT/Triple.h>
-#include <mcld/Support/TargetRegistry.h>
-
-#include "X86.h"
-#include "X86ELFSectLinker.h"
-
-using namespace mcld;
-
-namespace mcld {
-//===----------------------------------------------------------------------===//
-/// createX86SectLinker - the help funtion to create corresponding X86SectLinker
-///
-SectLinker* createX86SectLinker(const std::string &pTriple,
- SectLinkerOption &pOption,
- mcld::TargetLDBackend &pLDBackend)
-{
- Triple theTriple(pTriple);
- if (theTriple.isOSDarwin()) {
- assert(0 && "MachO linker has not supported yet");
- return NULL;
- }
- if (theTriple.isOSWindows()) {
- assert(0 && "COFF linker has not supported yet");
- return NULL;
- }
-
- if (theTriple.isArch32Bit())
- return new X86ELFSectLinker(pOption, pLDBackend);
-
- assert(0 && "X86_64 has not supported yet");
- return NULL;
-}
-
-} // namespace of mcld
-
-//==========================
-// X86SectLinker
-extern "C" void LLVMInitializeX86SectLinker() {
- // Register the linker frontend
- mcld::TargetRegistry::RegisterSectLinker(TheX86Target, createX86SectLinker);
-}
-
diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp
index b036137..9b5a24e 100644
--- a/lib/Target/X86/X86TargetMachine.cpp
+++ b/lib/Target/X86/X86TargetMachine.cpp
@@ -8,12 +8,11 @@
//===----------------------------------------------------------------------===//
#include "X86TargetMachine.h"
-#include "mcld/Target/TargetMachine.h"
-#include "mcld/Support/TargetRegistry.h"
-#include "mcld/MC/MCLDInfo.h"
#include "X86.h"
+#include <mcld/Target/TargetMachine.h>
+#include <mcld/Support/TargetRegistry.h>
-extern "C" void LLVMInitializeX86LDTarget() {
+extern "C" void MCLDInitializeX86LDTarget() {
// Register createTargetMachine function pointer to mcld::Target
mcld::RegisterTargetMachine<mcld::X86TargetMachine> X(mcld::TheX86Target);
}
@@ -21,14 +20,10 @@
mcld::X86TargetMachine::X86TargetMachine(llvm::TargetMachine& pPM,
const mcld::Target &pTarget,
const std::string& pTriple)
- : mcld::LLVMTargetMachine(pPM, pTarget, pTriple) {
- // arg1 - the number of total attributes
- // arg2 - the most possible number of input files
- m_pLDInfo = new MCLDInfo(pTriple, 32, 64);
+ : mcld::MCLDTargetMachine(pPM, pTarget, pTriple) {
}
mcld::X86TargetMachine::~X86TargetMachine()
{
- delete m_pLDInfo;
}
diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h
index 3ba9e59..9034741 100644
--- a/lib/Target/X86/X86TargetMachine.h
+++ b/lib/Target/X86/X86TargetMachine.h
@@ -8,30 +8,19 @@
//===----------------------------------------------------------------------===//
#ifndef MCLD_X86_TARGET_MACHINE_H
#define MCLD_X86_TARGET_MACHINE_H
-#include "mcld/Target/TargetMachine.h"
#include "X86.h"
+#include <mcld/Target/TargetMachine.h>
-namespace mcld
+namespace mcld {
+
+class X86TargetMachine : public MCLDTargetMachine
{
-
-class X86TargetMachine : public LLVMTargetMachine
-{
-protected:
- MCLDInfo *m_pLDInfo;
-
public:
X86TargetMachine(llvm::TargetMachine &pTM,
- const mcld::Target &pTarget,
- const std::string &pTriple);
+ const mcld::Target &pTarget,
+ const std::string &pTriple);
virtual ~X86TargetMachine();
-
- mcld::MCLDInfo& getLDInfo()
- { return *m_pLDInfo; }
-
- const mcld::MCLDInfo& getLDInfo() const
- { return *m_pLDInfo; }
-
};
} // namespace of mcld
diff --git a/tools/llvm-mcld/llvm-mcld.cpp b/tools/llvm-mcld/llvm-mcld.cpp
index f4201d2..28a18c6 100644
--- a/tools/llvm-mcld/llvm-mcld.cpp
+++ b/tools/llvm-mcld/llvm-mcld.cpp
@@ -6,20 +6,21 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/Target/TargetMachine.h>
#include <mcld/Support/TargetSelect.h>
#include <mcld/Support/TargetRegistry.h>
#include <mcld/Support/CommandLine.h>
-#include <mcld/Support/DerivedPositionDependentOptions.h>
#include <mcld/Support/Path.h>
#include <mcld/Support/RealPath.h>
#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/FileHandle.h>
#include <mcld/Support/FileSystem.h>
#include <mcld/Support/raw_ostream.h>
+#include <mcld/Support/ToolOutputFile.h>
#include <mcld/LD/DiagnosticLineInfo.h>
#include <mcld/LD/TextDiagnosticPrinter.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/CodeGen/SectLinkerOption.h>
#include <llvm/Module.h>
#include <llvm/PassManager.h>
@@ -36,11 +37,28 @@
#include <llvm/Support/Signals.h>
#include <llvm/Support/TargetRegistry.h>
#include <llvm/Support/TargetSelect.h>
-#include <llvm/Support/ToolOutputFile.h>
#include <llvm/Support/Process.h>
#include <llvm/Target/TargetData.h>
#include <llvm/Target/TargetMachine.h>
+#if defined(HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#if defined(_MSC_VER)
+#include <io.h>
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+#endif
+
+
using namespace llvm;
#ifdef ENABLE_UNITTEST
@@ -230,19 +248,25 @@
//===----------------------------------------------------------------------===//
// Command Line Options
// There are four kinds of command line options:
-// 1. input, (may be a file, such as -m and /tmp/XXXX.o.)
-// 2. attribute of inputs, (describing the attributes of inputs, such as
-// --as-needed and --whole-archive. usually be positional.)
-// 3. scripting options, (represent a subset of link scripting language, such
-// as --defsym.)
-// 4. and general options. (the rest of options)
+// 1. Bitcode option. Used to represent a bitcode.
+// 2. Attribute options. Attributes describes the input file after them. For
+// example, --as-needed affects the input file after this option. Attribute
+// options are not attributes. Attribute options are the options that is
+// used to define a legal attribute.
+// 3. Scripting options, Used to represent a subset of link scripting
+// language, such as --defsym.
+// 4. General options. (the rest of options)
//===----------------------------------------------------------------------===//
-// General Options
+// Bitcode Options
+//===----------------------------------------------------------------------===//
static cl::opt<mcld::sys::fs::Path, false, llvm::cl::parser<mcld::sys::fs::Path> >
ArgBitcodeFilename("dB",
cl::desc("set default bitcode"),
cl::value_desc("bitcode"));
+//===----------------------------------------------------------------------===//
+// General Options
+//===----------------------------------------------------------------------===//
static cl::opt<mcld::sys::fs::Path, false, llvm::cl::parser<mcld::sys::fs::Path> >
ArgOutputFilename("o",
cl::desc("Output filename"),
@@ -259,7 +283,7 @@
cl::value_desc("directory"),
cl::ValueRequired);
-static cl::list<mcld::MCLDDirectory, bool, llvm::cl::parser<mcld::MCLDDirectory> >
+static cl::list<std::string>
ArgSearchDirList("L",
cl::ZeroOrMore,
cl::desc("Add path searchdir to the list of paths that ld will search for archive libraries and ld control scripts."),
@@ -379,6 +403,16 @@
cl::desc("Emit a position-independent executable file"),
cl::init(false));
+static cl::opt<bool>
+ArgRelocatable("relocatable",
+ cl::desc("Generate relocatable output"),
+ cl::init(false));
+
+static cl::alias
+ArgRelocatableAlias("r",
+ cl::desc("alias for --relocatable"),
+ cl::aliasopt(ArgRelocatable));
+
static cl::opt<Reloc::Model>
ArgRelocModel("relocation-model",
cl::desc("Choose relocation model"),
@@ -401,6 +435,7 @@
static cl::opt<std::string>
ArgDyld("dynamic-linker",
+ cl::ZeroOrMore,
cl::desc("Set the name of the dynamic linker."),
cl::value_desc("Program"));
@@ -426,114 +461,154 @@
"surround result strings only if the output is a tty"),
clEnumValEnd));
-//===----------------------------------------------------------------------===//
-// Inputs
-static cl::list<mcld::sys::fs::Path>
-ArgInputObjectFiles(cl::Positional,
- cl::desc("[input object files]"),
- cl::ZeroOrMore);
+/// @{
+/// @name FIXME: begin of unsupported options
+/// @}
+static cl::opt<bool>
+ArgGCSections("gc-sections",
+ cl::desc("Enable garbage collection of unused input sections."),
+ cl::init(false));
+
+static cl::opt<bool>
+ArgNoGCSections("no-gc-sections",
+ cl::desc("disable garbage collection of unused input sections."),
+ cl::init(false));
+
+namespace icf {
+enum Mode {
+ None,
+ All,
+ Safe
+};
+} // namespace of icf
+
+static cl::opt<icf::Mode>
+ArgICF("icf",
+ cl::desc("Identical Code Folding"),
+ cl::init(icf::None),
+ cl::values(
+ clEnumValN(icf::None, "none",
+ "do not perform cold folding"),
+ clEnumValN(icf::All, "all",
+ "always preform cold folding"),
+ clEnumValN(icf::Safe, "safe",
+ "Folds ctors, dtors and functions whose pointers are definitely not taken."),
+ clEnumValEnd));
+
+// FIXME: add this to target options?
+static cl::opt<bool>
+ArgFIXCA8("fix-cortex-a8",
+ cl::desc("Enable Cortex-A8 Thumb-2 branch erratum fix"),
+ cl::init(false));
+
+static cl::opt<bool>
+ArgDiscardLocals("discard-locals",
+ cl::desc("Delete all temporary local symbols."),
+ cl::init(false));
+
+static cl::alias
+ArgDiscardLocalsAlias("X",
+ cl::desc("alias for --discard-locals"),
+ cl::aliasopt(ArgDiscardLocals));
+
+static cl::opt<bool>
+ArgDiscardAll("discard-all",
+ cl::desc("Delete all local symbols."),
+ cl::init(false));
+
+static cl::alias
+ArgDiscardAllAlias("x",
+ cl::desc("alias for --discard-all"),
+ cl::aliasopt(ArgDiscardAll));
+
+static cl::opt<bool>
+ArgNMagic("nmagic",
+ cl::desc("Do not page align data"),
+ cl::init(false));
+
+static cl::alias
+ArgNMagicAlias("n",
+ cl::desc("alias for --nmagic"),
+ cl::aliasopt(ArgNMagic));
+
+static cl::opt<bool>
+ArgOMagic("omagic",
+ cl::desc("Do not page align data, do not make text readonly"),
+ cl::init(false));
+
+static cl::alias
+ArgOMagicAlias("N",
+ cl::desc("alias for --omagic"),
+ cl::aliasopt(ArgOMagic));
+
+static cl::opt<bool>
+ArgStripDebug("strip-debug",
+ cl::desc("Omit debugger symbol information from the output file."),
+ cl::init(false));
+
+static cl::alias
+ArgStripDebugAlias("S",
+ cl::desc("alias for --strip-debug"),
+ cl::aliasopt(ArgStripDebug));
+
+static cl::opt<bool>
+ArgExportDynamic("export-dynamic",
+ cl::desc("Export all dynamic symbols"),
+ cl::init(false));
+
+static cl::alias
+ArgExportDynamicAlias("E",
+ cl::desc("alias for --export-dynamic"),
+ cl::aliasopt(ArgExportDynamic));
+
+static cl::opt<std::string>
+ArgEmulation("m",
+ cl::desc("Set GNU linker emulation"),
+ cl::value_desc("emulation"));
+
+static cl::opt<std::string>
+ArgRuntimePath("rpath",
+ cl::desc("Add a directory to the runtime library search path"),
+ cl::value_desc("dir"));
+
+static cl::opt<std::string>
+ArgRuntimePathLink("rpath-link",
+ cl::desc("Add a directory to the link time library search path"),
+ cl::value_desc("dir"));
static cl::list<std::string>
-ArgNameSpecList("l",
- cl::ZeroOrMore,
- cl::desc("Add the archive or object file specified by namespec to the list of files to link."),
- cl::value_desc("namespec"),
- cl::Prefix);
+ArgExcludeLIBS("exclude-libs",
+ cl::CommaSeparated,
+ cl::desc("Exclude libraries from automatic export"),
+ cl::value_desc("lib1,lib2,..."));
+
+static cl::opt<std::string>
+ArgBuildID("build-id",
+ cl::desc("Request creation of \".note.gnu.build-id\" ELF note section."),
+ cl::value_desc("style"));
+
+static cl::opt<std::string>
+ArgForceUndefined("u",
+ cl::desc("Force symbol to be undefined in the output file"),
+ cl::value_desc("symbol"));
static cl::alias
-ArgNameSpecListAlias("library",
- cl::desc("alias for -l"),
- cl::aliasopt(ArgNameSpecList));
+ArgForceUndefinedAlias("undefined",
+ cl::desc("alias for -u"),
+ cl::aliasopt(ArgForceUndefined));
-static cl::list<bool>
-ArgStartGroupList("start-group",
- cl::ValueDisallowed,
- cl::desc("start to record a group of archives"));
+/// @{
+/// @name FIXME: end of unsupported options
+/// @}
-static cl::alias
-ArgStartGroupListAlias("(",
- cl::desc("alias for --start-group"),
- cl::aliasopt(ArgStartGroupList));
-
-static cl::list<bool>
-ArgEndGroupList("end-group",
- cl::ValueDisallowed,
- cl::desc("stop recording a group of archives"));
-
-static cl::alias
-ArgEndGroupListAlias(")",
- cl::desc("alias for --end-group"),
- cl::aliasopt(ArgEndGroupList));
-
-//===----------------------------------------------------------------------===//
-// Attributes of Inputs
-static cl::list<bool>
-ArgWholeArchiveList("whole-archive",
- cl::ValueDisallowed,
- cl::desc("For each archive mentioned on the command line after the --whole-archive option, include all object files in the archive."));
-
-static cl::list<bool>
-ArgNoWholeArchiveList("no-whole-archive",
- cl::ValueDisallowed,
- cl::desc("Turn off the effect of the --whole-archive option for subsequent archive files."));
-
-static cl::list<bool>
-ArgAsNeededList("as-needed",
- cl::ValueDisallowed,
- cl::desc("This option affects ELF DT_NEEDED tags for dynamic libraries mentioned on the command line after the --as-needed option."));
-
-static cl::list<bool>
-ArgNoAsNeededList("no-as-needed",
- cl::ValueDisallowed,
- cl::desc("Turn off the effect of the --as-needed option for subsequent dynamic libraries"));
-
-static cl::list<bool>
-ArgAddNeededList("add-needed",
- cl::ValueDisallowed,
- cl::desc("--add-needed causes DT_NEEDED tags are always emitted for those libraries from DT_NEEDED tags. This is the default behavior."));
-
-static cl::list<bool>
-ArgNoAddNeededList("no-add-needed",
- cl::ValueDisallowed,
- cl::desc("--no-add-needed causes DT_NEEDED tags will never be emitted for those libraries from DT_NEEDED tags"));
-
-static cl::list<bool>
-ArgBDynamicList("Bdynamic",
- cl::ValueDisallowed,
- cl::desc("Link against dynamic library"));
-
-static cl::alias
-ArgBDynamicListAlias1("dy",
- cl::desc("alias for --Bdynamic"),
- cl::aliasopt(ArgBDynamicList));
-
-static cl::alias
-ArgBDynamicListAlias2("call_shared",
- cl::desc("alias for --Bdynamic"),
- cl::aliasopt(ArgBDynamicList));
-
-static cl::list<bool>
-ArgBStaticList("Bstatic",
- cl::ValueDisallowed,
- cl::desc("Link against static library"));
-
-static cl::alias
-ArgBStaticListAlias1("dn",
- cl::desc("alias for --Bstatic"),
- cl::aliasopt(ArgBStaticList));
-
-static cl::alias
-ArgBStaticListAlias2("static",
- cl::desc("alias for --Bstatic"),
- cl::aliasopt(ArgBStaticList));
-
-static cl::alias
-ArgBStaticListAlias3("non_shared",
- cl::desc("alias for --Bstatic"),
- cl::aliasopt(ArgBStaticList));
+static cl::opt<bool>
+ArgWarnSharedTextrel("warn-shared-textrel",
+ cl::desc("Warn if adding DT_TEXTREL in a shared object."),
+ cl::init(false));
//===----------------------------------------------------------------------===//
// Scripting Options
+//===----------------------------------------------------------------------===//
static cl::list<std::string>
ArgWrapList("wrap",
cl::ZeroOrMore,
@@ -546,15 +621,37 @@
cl::desc("Use a portable function fo symbol."),
cl::value_desc("symbol"));
-//===----------------------------------------------------------------------===//
-/// non-member functions
+static cl::list<std::string>
+ArgAddressMapList("section-start",
+ cl::ZeroOrMore,
+ cl::desc("Locate a output section at the given absolute address"),
+ cl::value_desc("Set address of section"),
+ cl::Prefix);
+static cl::opt<unsigned long long>
+ArgBssSegAddr("Tbss",
+ cl::desc("Set the address of the bss segment"),
+ cl::init(-1U));
+
+static cl::opt<unsigned long long>
+ArgDataSegAddr("Tdata",
+ cl::desc("Set the address of the data segment"),
+ cl::init(-1U));
+
+static cl::opt<unsigned long long>
+ArgTextSegAddr("Ttext",
+ cl::desc("Set the address of the text segment"),
+ cl::init(-1U));
+
+//===----------------------------------------------------------------------===//
+// non-member functions
+//===----------------------------------------------------------------------===//
/// GetOutputStream - get the output stream.
-static tool_output_file *GetOutputStream(const char* pTargetName,
- Triple::OSType pOSType,
- mcld::CodeGenFileType pFileType,
- const mcld::sys::fs::Path& pInputFilename,
- mcld::sys::fs::Path& pOutputFilename)
+static mcld::ToolOutputFile *GetOutputStream(const char* pTargetName,
+ Triple::OSType pOSType,
+ mcld::CodeGenFileType pFileType,
+ const mcld::sys::fs::Path& pInputFilename,
+ mcld::sys::fs::Path& pOutputFilename)
{
if (pOutputFilename.empty()) {
if (0 == pInputFilename.native().compare("-"))
@@ -589,6 +686,19 @@
}
break;
+ case mcld::CGFT_PARTIAL: {
+ if (Triple::Win32 == pOSType) {
+ if (0 == pInputFilename.native().compare("-"))
+ pOutputFilename.assign("_out");
+ else
+ pOutputFilename.assign(pInputFilename.stem().native());
+ pOutputFilename.native() += ".obj";
+ }
+ else
+ pOutputFilename.assign("a.out");
+ }
+ break;
+
case mcld::CGFT_DSOFile: {
if (Triple::Win32 == pOSType) {
if (0 == pInputFilename.native().compare("-"))
@@ -623,31 +733,28 @@
} // end of ! pInputFilename == "-"
} // end of if empty pOutputFilename
- // Decide if we need "binary" output.
- unsigned int fd_flags = 0x0;
+ mcld::FileHandle::Permission permission;
switch (pFileType) {
default: assert(0 && "Unknown file type");
case mcld::CGFT_ASMFile:
- break;
case mcld::CGFT_OBJFile:
+ case mcld::CGFT_PARTIAL:
+ permission = 0644;
+ break;
case mcld::CGFT_DSOFile:
case mcld::CGFT_EXEFile:
case mcld::CGFT_NULLFile:
- fd_flags |= raw_fd_ostream::F_Binary;
+ permission = 0755;
break;
}
// Open the file.
- std::string err_mesg;
- tool_output_file *result_output =
- new tool_output_file(pOutputFilename.c_str(),
- err_mesg,
- fd_flags);
- if (!err_mesg.empty()) {
- errs() << err_mesg << '\n';
- delete result_output;
- return NULL;
- }
+ mcld::ToolOutputFile* result_output =
+ new mcld::ToolOutputFile(pOutputFilename,
+ mcld::FileHandle::ReadWrite |
+ mcld::FileHandle::Create |
+ mcld::FileHandle::Truncate,
+ permission);
return result_output;
}
@@ -658,46 +765,79 @@
return term && (0 != strcmp(term, "dumb"));
}
-static bool ProcessLinkerOptionsFromCommand(mcld::MCLDInfo& pLDInfo) {
+static bool ProcessLinkerOptionsFromCommand(mcld::LinkerConfig& pConfig) {
// ----- Set up General Options ----- //
+ // set up colorize
+ switch (ArgColor) {
+ case color::Never:
+ pConfig.options().setColor(false);
+ break;
+ case color::Always:
+ pConfig.options().setColor(true);
+ break;
+ case color::Auto:
+ bool color_option = ShouldColorize() &&
+ llvm::sys::Process::FileDescriptorIsDisplayed(STDOUT_FILENO);
+ pConfig.options().setColor(color_option);
+ break;
+ }
+
+ mcld::outs().setColor(pConfig.options().color());
+ mcld::errs().setColor(pConfig.options().color());
+
// set up soname
- pLDInfo.output().setSOName(ArgSOName);
+ pConfig.options().setSOName(ArgSOName);
+
+ // -shared or -pie
+ if (true == ArgShared || true == ArgPIE) {
+ ArgFileType = mcld::CGFT_DSOFile;
+ }
+ else if (true == ArgRelocatable) {
+ ArgFileType = mcld::CGFT_PARTIAL;
+ }
+
+ // -V
+ if (ArgVersion) {
+ mcld::outs() << "MCLinker - "
+ << mcld::LinkerConfig::version()
+ << "\n";
+ }
// set up sysroot
if (!ArgSysRoot.empty()) {
if (exists(ArgSysRoot) && is_directory(ArgSysRoot))
- pLDInfo.options().setSysroot(ArgSysRoot);
+ pConfig.options().setSysroot(ArgSysRoot);
}
// add all search directories
- cl::list<mcld::MCLDDirectory>::iterator sd;
- cl::list<mcld::MCLDDirectory>::iterator sdEnd = ArgSearchDirList.end();
+ cl::list<std::string>::iterator sd;
+ cl::list<std::string>::iterator sdEnd = ArgSearchDirList.end();
for (sd=ArgSearchDirList.begin(); sd!=sdEnd; ++sd) {
- if (sd->isInSysroot())
- sd->setSysroot(pLDInfo.options().sysroot());
- if (exists(sd->path()) && is_directory(sd->path())) {
- pLDInfo.options().directories().add(*sd);
- }
- else {
+ if (!pConfig.options().directories().insert(*sd)) {
// FIXME: need a warning function
errs() << "WARNING: can not open search directory `-L"
- << sd->name()
+ << *sd
<< "'.\n";
}
}
- pLDInfo.options().setPIE(ArgPIE);
- pLDInfo.options().setTrace(ArgTrace);
- pLDInfo.options().setVerbose(ArgVerbose);
- pLDInfo.options().setMaxErrorNum(ArgMaxErrorNum);
- pLDInfo.options().setMaxWarnNum(ArgMaxWarnNum);
- pLDInfo.options().setEntry(ArgEntry);
- pLDInfo.options().setBsymbolic(ArgBsymbolic);
- pLDInfo.options().setBgroup(ArgBgroup);
- pLDInfo.options().setDyld(ArgDyld);
- pLDInfo.options().setNoUndefined(ArgNoUndefined);
- pLDInfo.options().setMulDefs(ArgAllowMulDefs);
- pLDInfo.options().setEhFrameHdr(ArgEhFrameHdr);
+ pConfig.options().setPIE(ArgPIE);
+ pConfig.options().setTrace(ArgTrace);
+ pConfig.options().setVerbose(ArgVerbose);
+ pConfig.options().setMaxErrorNum(ArgMaxErrorNum);
+ pConfig.options().setMaxWarnNum(ArgMaxWarnNum);
+ pConfig.options().setEntry(ArgEntry);
+ pConfig.options().setBsymbolic(ArgBsymbolic);
+ pConfig.options().setBgroup(ArgBgroup);
+ pConfig.options().setDyld(ArgDyld);
+ pConfig.options().setNoUndefined(ArgNoUndefined);
+ pConfig.options().setMulDefs(ArgAllowMulDefs);
+ pConfig.options().setEhFrameHdr(ArgEhFrameHdr);
+ pConfig.options().setNMagic(ArgNMagic);
+ pConfig.options().setOMagic(ArgOMagic);
+ pConfig.options().setStripDebug(ArgStripDebug);
+ pConfig.options().setExportDynamic(ArgExportDynamic);
+ pConfig.options().setWarnSharedTextrel(ArgWarnSharedTextrel);
// set up rename map, for --wrap
cl::list<std::string>::iterator wname;
@@ -707,7 +847,7 @@
// add wname -> __wrap_wname
mcld::StringEntry<llvm::StringRef>* to_wrap =
- pLDInfo.scripts().renameMap().insert(*wname, exist);
+ pConfig.scripts().renameMap().insert(*wname, exist);
std::string to_wrap_str = "__wrap_" + *wname;
to_wrap->setValue(to_wrap_str);
@@ -718,7 +858,7 @@
// add __real_wname -> wname
std::string from_real_str = "__real_" + *wname;
mcld::StringEntry<llvm::StringRef>* from_real =
- pLDInfo.scripts().renameMap().insert(from_real_str, exist);
+ pConfig.scripts().renameMap().insert(from_real_str, exist);
from_real->setValue(*wname);
if (exist)
mcld::warning(mcld::diag::rewrap) << *wname << from_real_str;
@@ -732,7 +872,7 @@
// add pname -> pname_portable
mcld::StringEntry<llvm::StringRef>* to_port =
- pLDInfo.scripts().renameMap().insert(*pname, exist);
+ pConfig.scripts().renameMap().insert(*pname, exist);
std::string to_port_str = *pname + "_portable";
to_port->setValue(to_port_str);
@@ -743,154 +883,88 @@
// add __real_pname -> pname
std::string from_real_str = "__real_" + *pname;
mcld::StringEntry<llvm::StringRef>* from_real =
- pLDInfo.scripts().renameMap().insert(from_real_str, exist);
+ pConfig.scripts().renameMap().insert(from_real_str, exist);
from_real->setValue(*pname);
if (exist)
mcld::warning(mcld::diag::rewrap) << *pname << from_real_str;
} // end of for
- // set up colorize
- switch (ArgColor) {
- case color::Never:
- pLDInfo.options().setColor(false);
- break;
- case color::Always:
- pLDInfo.options().setColor(true);
- break;
- case color::Auto:
- bool color_option = ShouldColorize() &&
- llvm::sys::Process::FileDescriptorIsDisplayed(STDOUT_FILENO);
- pLDInfo.options().setColor(color_option);
- break;
- }
-
// add -z options
cl::list<mcld::ZOption>::iterator zOpt;
cl::list<mcld::ZOption>::iterator zOptEnd = ArgZOptionList.end();
for (zOpt = ArgZOptionList.begin(); zOpt != zOptEnd; ++zOpt) {
- pLDInfo.options().addZOption(*zOpt);
+ pConfig.options().addZOption(*zOpt);
}
- // ----- Set up Script Options ----- //
-
- return true;
-}
-
-static bool ProcessLinkerInputsFromCommand(mcld::SectLinkerOption &pOption) {
- // ----- Set up Inputs ----- //
- // add all start-group
- cl::list<bool>::iterator sg;
- cl::list<bool>::iterator sgEnd = ArgStartGroupList.end();
- for (sg=ArgStartGroupList.begin(); sg!=sgEnd; ++sg) {
- // calculate position
- pOption.appendOption(new mcld::StartGroupOption(
- ArgStartGroupList.getPosition(sg-ArgStartGroupList.begin())));
+ if (ArgGCSections) {
+ mcld::warning(mcld::diag::warn_unsupported_option) << ArgGCSections.ArgStr;
}
- // add all end-group
- cl::list<bool>::iterator eg;
- cl::list<bool>::iterator egEnd = ArgEndGroupList.end();
- for (eg=ArgEndGroupList.begin(); eg!=egEnd; ++eg) {
- // calculate position
- pOption.appendOption(new mcld::EndGroupOption(
- ArgEndGroupList.getPosition(eg-ArgEndGroupList.begin())));
+ // set up icf mode
+ switch (ArgICF) {
+ case icf::None:
+ break;
+ case icf::All:
+ case icf::Safe:
+ default:
+ mcld::warning(mcld::diag::warn_unsupported_option) << ArgICF.ArgStr;
+ break;
}
- // add all namespecs
- cl::list<std::string>::iterator ns;
- cl::list<std::string>::iterator nsEnd = ArgNameSpecList.end();
- for (ns=ArgNameSpecList.begin(); ns!=nsEnd; ++ns) {
- // calculate position
- pOption.appendOption(new mcld::NamespecOption(
- ArgNameSpecList.getPosition(ns-ArgNameSpecList.begin()),
- *ns));
+ if (ArgFIXCA8) {
+ mcld::warning(mcld::diag::warn_unsupported_option) << ArgFIXCA8.ArgStr;
}
- // add all object files
- cl::list<mcld::sys::fs::Path>::iterator obj;
- cl::list<mcld::sys::fs::Path>::iterator objEnd = ArgInputObjectFiles.end();
- for (obj=ArgInputObjectFiles.begin(); obj!=objEnd; ++obj) {
- // calculate position
- pOption.appendOption(new mcld::InputFileOption(
- ArgInputObjectFiles.getPosition(obj-ArgInputObjectFiles.begin()),
- *obj));
+ if (ArgDiscardLocals) {
+ mcld::warning(mcld::diag::warn_unsupported_option) << ArgDiscardLocals.ArgStr;
}
- // ----- Set up Attributes of Inputs ----- //
- // --whole-archive
- cl::list<bool>::iterator attr = ArgWholeArchiveList.begin();
- cl::list<bool>::iterator attrEnd = ArgWholeArchiveList.end();
- for (; attr!=attrEnd; ++attr) {
- pOption.appendOption(new mcld::WholeArchiveOption(
- ArgWholeArchiveList.getPosition(attr-ArgWholeArchiveList.begin())));
+ if (ArgDiscardAll) {
+ mcld::warning(mcld::diag::warn_unsupported_option) << ArgDiscardAll.ArgStr;
}
- // --no-whole-archive
- attr = ArgNoWholeArchiveList.begin();
- attrEnd = ArgNoWholeArchiveList.end();
- for (; attr!=attrEnd; ++attr) {
- pOption.appendOption(new mcld::NoWholeArchiveOption(
- ArgNoWholeArchiveList.getPosition(attr-ArgNoWholeArchiveList.begin())));
+ // add address mappings
+ // -Ttext
+ if (-1U != ArgTextSegAddr) {
+ bool exist = false;
+ mcld::StringEntry<uint64_t>* text_mapping =
+ pConfig.scripts().addressMap().insert(".text", exist);
+ text_mapping->setValue(ArgTextSegAddr);
}
-
- // --as-needed
- attr = ArgAsNeededList.begin();
- attrEnd = ArgAsNeededList.end();
- while(attr != attrEnd) {
- pOption.appendOption(new mcld::AsNeededOption(
- ArgAsNeededList.getPosition(attr-ArgAsNeededList.begin())));
- ++attr;
+ // -Tdata
+ if (-1U != ArgDataSegAddr) {
+ bool exist = false;
+ mcld::StringEntry<uint64_t>* data_mapping =
+ pConfig.scripts().addressMap().insert(".data", exist);
+ data_mapping->setValue(ArgDataSegAddr);
}
-
- // --no-as-needed
- attr = ArgNoAsNeededList.begin();
- attrEnd = ArgNoAsNeededList.end();
- while(attr != attrEnd) {
- pOption.appendOption(new mcld::NoAsNeededOption(
- ArgNoAsNeededList.getPosition(attr-ArgNoAsNeededList.begin())));
- ++attr;
+ // -Tbss
+ if (-1U != ArgBssSegAddr) {
+ bool exist = false;
+ mcld::StringEntry<uint64_t>* bss_mapping =
+ pConfig.scripts().addressMap().insert(".bss", exist);
+ bss_mapping->setValue(ArgBssSegAddr);
}
-
- // --add-needed
- attr = ArgAddNeededList.begin();
- attrEnd = ArgAddNeededList.end();
- while(attr != attrEnd) {
- pOption.appendOption(new mcld::AddNeededOption(
- ArgAddNeededList.getPosition(attr-ArgAddNeededList.begin())));
- ++attr;
- }
-
- // --no-add-needed
- attr = ArgNoAddNeededList.begin();
- attrEnd = ArgNoAddNeededList.end();
- while(attr != attrEnd) {
- pOption.appendOption(new mcld::NoAddNeededOption(
- ArgNoAddNeededList.getPosition(attr-ArgNoAddNeededList.begin())));
- ++attr;
- }
-
- // -Bdynamic
- attr = ArgBDynamicList.begin();
- attrEnd = ArgBDynamicList.end();
- while(attr != attrEnd) {
- pOption.appendOption(new mcld::BDynamicOption(
- ArgBDynamicList.getPosition(attr-ArgBDynamicList.begin())));
- }
-
- // -Bstatic
- attr = ArgBStaticList.begin();
- attrEnd = ArgBStaticList.end();
- while(attr != attrEnd) {
- pOption.appendOption(new mcld::BStaticOption(
- ArgBStaticList.getPosition(attr-ArgBStaticList.begin())));
- ++attr;
+ // --section-start SECTION=ADDRESS
+ for (cl::list<std::string>::iterator
+ it = ArgAddressMapList.begin(), ie = ArgAddressMapList.end();
+ it != ie; ++it) {
+ // FIXME: Add a cl::parser
+ size_t pos = (*it).find_last_of('=');
+ llvm::StringRef script(*it);
+ uint64_t address = 0x0;
+ script.substr(pos + 1).getAsInteger(0, address);
+ bool exist = false;
+ mcld::StringEntry<uint64_t>* addr_mapping =
+ pConfig.scripts().addressMap().insert(script.substr(0, pos), exist);
+ addr_mapping->setValue(address);
}
return true;
}
-int main( int argc, char* argv[] )
+int main(int argc, char* argv[])
{
LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
@@ -909,26 +983,27 @@
InitializeAllTargetMCs();
mcld::InitializeAllTargets();
mcld::InitializeAllLinkers();
+ mcld::InitializeAllEmulations();
mcld::InitializeAllDiagnostics();
// Load the module to be compiled...
- std::auto_ptr<Module> M;
+ std::auto_ptr<llvm::Module> M;
- // -shared
- if (true == ArgShared) {
- ArgFileType = mcld::CGFT_DSOFile;
- }
+ // Load the module to be linked...
+ mcld::Module LDIRModule;
- // -V
- if (ArgVersion) {
- outs() << "MCLinker - ";
- outs() << mcld::MCLDInfo::version();
- outs() << "\n";
+ mcld::LinkerConfig LDConfig;
+
+ // Process the linker input from the command line
+ if (!ProcessLinkerOptionsFromCommand(LDConfig)) {
+ errs() << argv[0] << ": failed to process linker options from command line!\n";
+ return 1;
}
if (ArgBitcodeFilename.empty() &&
(mcld::CGFT_DSOFile != ArgFileType &&
- mcld::CGFT_EXEFile != ArgFileType)) {
+ mcld::CGFT_EXEFile != ArgFileType &&
+ mcld::CGFT_PARTIAL != ArgFileType)) {
// If the file is not given, forcefully read from stdin
if (ArgVerbose >= 0) {
errs() << "** The bitcode/llvm asm file is not given. Read from stdin.\n"
@@ -1011,6 +1086,8 @@
return 1;
}
}
+ // Set up mcld::LinkerConfig
+ LDConfig.setTriple(TheTriple);
// Package up features to be passed to target/subtarget
std::string FeaturesStr;
@@ -1060,34 +1137,26 @@
Options.TrapFuncName = TrapFuncName;
Options.EnableSegmentedStacks = SegmentedStacks;
- std::auto_ptr<mcld::LLVMTargetMachine> target_machine(
+ std::auto_ptr<mcld::MCLDTargetMachine> target_machine(
TheTarget->createTargetMachine(TheTriple.getTriple(),
MCPU, FeaturesStr, Options,
ArgRelocModel, CMModel, OLvl));
assert(target_machine.get() && "Could not allocate target machine!");
- mcld::LLVMTargetMachine &TheTargetMachine = *target_machine.get();
+ mcld::MCLDTargetMachine &TheTargetMachine = *target_machine.get();
TheTargetMachine.getTM().setMCUseLoc(false);
TheTargetMachine.getTM().setMCUseCFI(false);
- // Set up mcld::outs() and mcld::errs()
- InitializeOStreams(TheTargetMachine.getLDInfo());
-
- // Set up MsgHandler
+ // FIXME: Move the initialization of LineInfo to mcld::Linker when we
+ // finish LineInfo's implementation.
OwningPtr<mcld::DiagnosticLineInfo>
diag_line_info(TheTarget->createDiagnosticLineInfo(*TheTarget,
TheTriple.getTriple()));
- OwningPtr<mcld::DiagnosticPrinter>
- diag_printer(new mcld::TextDiagnosticPrinter(mcld::errs(),
- TheTargetMachine.getLDInfo()));
- mcld::InitializeDiagnosticEngine(TheTargetMachine.getLDInfo(),
- diag_line_info.take(),
- diag_printer.get());
-
+ mcld::getDiagnosticEngine().setLineInfo(*diag_line_info.take());
// Figure out where we are going to send the output...
- OwningPtr<tool_output_file>
+ OwningPtr<mcld::ToolOutputFile>
Out(GetOutputStream(TheTarget->get()->getName(),
TheTriple.getOS(),
ArgFileType,
@@ -1110,30 +1179,14 @@
// Override default to generate verbose assembly.
TheTargetMachine.getTM().setAsmVerbosityDefault(true);
- // Process the linker input from the command line
- mcld::SectLinkerOption *LinkerOpt =
- new mcld::SectLinkerOption(TheTargetMachine.getLDInfo());
-
- if (!ProcessLinkerOptionsFromCommand(TheTargetMachine.getLDInfo())) {
- errs() << argv[0] << ": failed to process linker options from command line!\n";
- return 1;
- }
-
- if (!ProcessLinkerInputsFromCommand(*LinkerOpt)) {
- errs() << argv[0] << ": failed to process inputs from command line!\n";
- return 1;
- }
-
{
- formatted_raw_ostream FOS(Out->os());
-
// Ask the target to add backend passes as necessary.
if( TheTargetMachine.addPassesToEmitFile(PM,
- FOS,
- ArgOutputFilename.native(),
+ *Out,
ArgFileType,
OLvl,
- LinkerOpt,
+ LDIRModule,
+ LDConfig,
NoVerify)) {
errs() << argv[0] << ": target does not support generation of this"
<< " file type!\n";
@@ -1148,20 +1201,6 @@
// Declare success.
Out->keep();
-
- // clean up
- delete LinkerOpt;
-
- if (0 != diag_printer->getNumErrors()) {
- // If we reached here, we are failing ungracefully. Run the interrupt handlers
- // to make sure any special cleanups get done, in particular that we remove
- // files registered with RemoveFileOnSignal.
- llvm::sys::RunInterruptHandlers();
- diag_printer->finish();
- exit(1);
- }
-
- diag_printer->finish();
return 0;
}
diff --git a/tools/mcld/include/alone/Linker.h b/tools/mcld/include/alone/Linker.h
index 9321e94..b0bdc5e 100644
--- a/tools/mcld/include/alone/Linker.h
+++ b/tools/mcld/include/alone/Linker.h
@@ -14,12 +14,17 @@
namespace mcld {
+class Module;
class TargetLDBackend;
-class MCLDDriver;
-class MemoryFactory;
-class MCLDInfo;
+class ObjectLinker;
+class ContextFactory;
+class LinkerConfig;
class TreeIteratorBase;
class Input;
+class InputFactory;
+class InputBuilder;
+class MemoryArea;
+class MemoryAreaFactory;
namespace sys { namespace fs {
@@ -31,7 +36,6 @@
namespace alone {
-class MemoryFactory;
class LinkerConfig;
class Linker {
@@ -50,19 +54,23 @@
kReadSections,
kReadSymbols,
kAddAdditionalSymbols,
- kMaxErrorCode,
+ kMaxErrorCode
};
static const char *GetErrorString(enum ErrorCode pErrCode);
private:
+ const mcld::LinkerConfig *mLDConfig;
+ mcld::Module *mModule;
mcld::TargetLDBackend *mBackend;
- mcld::MCLDDriver *mDriver;
- MemoryFactory *mMemAreaFactory;
- mcld::MCLDInfo *mLDInfo;
+ mcld::ObjectLinker *mObjLinker;
+ mcld::InputFactory *mInputFactory;
+ mcld::MemoryAreaFactory *mMemAreaFactory;
+ mcld::ContextFactory *mContextFactory;
+ mcld::InputBuilder *mBuilder;
mcld::TreeIteratorBase *mRoot;
- bool mShared;
std::string mSOName;
+ mcld::MemoryArea* mOutput;
public:
Linker();
diff --git a/tools/mcld/include/alone/Support/LinkerConfig.h b/tools/mcld/include/alone/Support/LinkerConfig.h
index f29e557..0aa3277 100644
--- a/tools/mcld/include/alone/Support/LinkerConfig.h
+++ b/tools/mcld/include/alone/Support/LinkerConfig.h
@@ -12,7 +12,7 @@
#include <string>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/Support/TargetRegistry.h>
#include <mcld/LD/DiagnosticLineInfo.h>
#include <mcld/LD/DiagnosticPrinter.h>
@@ -25,7 +25,6 @@
// Available Configurations
//===--------------------------------------------------------------------===//
const std::string mTriple;
- bool mShared;
std::string mSOName;
private:
@@ -35,7 +34,7 @@
const mcld::Target *mTarget;
bool initializeTarget();
- mcld::MCLDInfo *mLDInfo;
+ mcld::LinkerConfig *mLDConfig;
bool initializeLDInfo();
mcld::DiagnosticLineInfo *mDiagLineInfo;
@@ -43,6 +42,26 @@
bool initializeDiagnostic();
public:
+ enum ZOptionEnum {
+ kCombReloc = 1 << 0, ///< [on] -z combreloc, [off] -z nocombreloc
+ kDefs = 1 << 1, ///< -z defs
+ kExecStack = 1 << 2, ///< [on] -z execstack, [off] -z noexecstack
+ kInitFirst = 1 << 3, ///< -z initfirst
+ kInterPose = 1 << 4, ///< -z interpose
+ kLoadFltr = 1 << 5, ///< -z loadfltr
+ kMulDefs = 1 << 6, ///< -z muldefs
+ kNoCopyReloc = 1 << 7, ///< -z nocopyreloc
+ kNoDefaultLib = 1 << 8, ///< -z nodefaultlib
+ kNoDelete = 1 << 9, ///< -z nodelete
+ kNoDLOpen = 1 << 10, ///< -z nodlopen
+ kNoDump = 1 << 11, ///< -z nodump
+ kRelro = 1 << 12, ///< [on] -z relro, [off] -z norelro
+ kLazy = 1 << 13, ///< [on] -z lazy, [off] -z now
+ kOrigin = 1 << 14, ///< -z origin
+ kZOptionMask = 0xFFFF
+ };
+
+public:
//===--------------------------------------------------------------------===//
// Getters
//===--------------------------------------------------------------------===//
@@ -52,14 +71,13 @@
inline const mcld::Target *getTarget() const
{ return mTarget; }
- inline mcld::MCLDInfo* getLDInfo()
- { return mLDInfo; }
+ inline mcld::LinkerConfig* getLDConfig()
+ { return mLDConfig; }
- inline const mcld::MCLDInfo* getLDInfo() const
- { return mLDInfo; }
+ inline const mcld::LinkerConfig* getLDConfig() const
+ { return mLDConfig; }
- inline bool isShared() const
- { return mShared; }
+ bool isShared() const;
inline std::string getSOName() const
{ return mSOName; }
@@ -74,6 +92,8 @@
void setSysRoot(const std::string &pSysRoot);
+ void setZOption(unsigned int pOptions);
+
void addWrap(const std::string &pWrapSymbol);
void addPortable(const std::string &pPortableSymbol);
diff --git a/tools/mcld/include/alone/Support/MemoryFactory.h b/tools/mcld/include/alone/Support/MemoryFactory.h
deleted file mode 100644
index 132d20f..0000000
--- a/tools/mcld/include/alone/Support/MemoryFactory.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- MemoryFactory.h ----------------------------------------------------===//
-//
-// The MCLinker Project
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ALONE_SUPPORT_MEMORY_FACTORY_H
-#define ALONE_SUPPORT_MEMORY_FACTORY_H
-
-#include <mcld/Support/FileHandle.h>
-#include <mcld/Support/MemoryAreaFactory.h>
-
-namespace mcld {
-class MemoryArea;
-} // end namespace mcld
-
-namespace alone {
-
-class MemoryFactory : public mcld::MemoryAreaFactory {
-public:
- MemoryFactory() : mcld::MemoryAreaFactory(32) { }
-
- ~MemoryFactory() { }
-
- using mcld::MemoryAreaFactory::produce;
-
- mcld::MemoryArea* produce(void *pMemBuffer, size_t pSize)
- { return mcld::MemoryAreaFactory::create(pMemBuffer, pSize); }
-
- mcld::MemoryArea* produce(int pFD)
- { return mcld::MemoryAreaFactory::create(pFD, mcld::FileHandle::Unknown); }
-};
-
-} // end namespace alone
-
-#endif // ALONE_SUPPORT_MEMORY_FACTORY_H
diff --git a/tools/mcld/include/alone/Support/TargetLinkerConfigs.h b/tools/mcld/include/alone/Support/TargetLinkerConfigs.h
index 40bc812..3bb6b7b 100644
--- a/tools/mcld/include/alone/Support/TargetLinkerConfigs.h
+++ b/tools/mcld/include/alone/Support/TargetLinkerConfigs.h
@@ -74,6 +74,16 @@
#endif
{ };
+#if !defined(TARGET_BUILD)
+//===----------------------------------------------------------------------===//
+// General target
+//===----------------------------------------------------------------------===//
+class GeneralLinkerConfig : public LinkerConfig {
+public:
+ GeneralLinkerConfig(const std::string& pTriple);
+};
+#endif // !defined(TARGET_BUILD)
+
} // end namespace alone
#endif // ALONE_SUPPORT_LINKER_CONFIG_H
diff --git a/tools/mcld/lib/Core/Linker.cpp b/tools/mcld/lib/Core/Linker.cpp
index a9ebc1f..d3f1450 100644
--- a/tools/mcld/lib/Core/Linker.cpp
+++ b/tools/mcld/lib/Core/Linker.cpp
@@ -9,15 +9,18 @@
#include "alone/Linker.h"
#include "alone/Support/LinkerConfig.h"
-#include "alone/Support/MemoryFactory.h"
#include "alone/Support/Log.h"
#include <llvm/Support/ELF.h>
-#include <mcld/MC/MCLDDriver.h>
-#include <mcld/MC/InputTree.h>
-#include <mcld/MC/MCLinker.h>
-#include <mcld/MC/InputTree.h>
+#include <mcld/Module.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/InputTree.h>
+#include <mcld/Object/ObjectLinker.h>
+#include <mcld/Fragment/FragmentLinker.h>
+#include <mcld/MC/InputFactory.h>
+#include <mcld/MC/ContextFactory.h>
+#include <mcld/MC/InputBuilder.h>
#include <mcld/LD/LDSection.h>
#include <mcld/LD/LDContext.h>
#include <mcld/Target/TargetLDBackend.h>
@@ -72,13 +75,15 @@
// Linker
//===----------------------------------------------------------------------===//
Linker::Linker()
- : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL),
- mRoot(NULL), mShared(false) {
+ : mLDConfig(NULL), mModule(NULL), mBackend(NULL), mObjLinker(NULL),
+ mInputFactory(NULL), mMemAreaFactory(NULL), mContextFactory(NULL),
+ mBuilder(NULL), mRoot(NULL), mOutput(NULL) {
}
Linker::Linker(const LinkerConfig& pConfig)
- : mBackend(NULL), mDriver(NULL), mMemAreaFactory(NULL), mLDInfo(NULL),
- mRoot(NULL), mShared(false) {
+ : mLDConfig(NULL), mModule(NULL), mBackend(NULL), mObjLinker(NULL),
+ mInputFactory(NULL), mMemAreaFactory(NULL), mContextFactory(NULL),
+ mBuilder(NULL), mRoot(NULL), mOutput(NULL) {
const std::string &triple = pConfig.getTriple();
@@ -92,42 +97,57 @@
}
Linker::~Linker() {
- delete mDriver;
+ delete mModule;
+ delete mObjLinker;
+ // FIXME: current implementation can not change the order of deleting
+ // ObjectLinker and TargetLDBackend. Because the deletion of relocation list
+ // in FragmentLinker (FragmentLinker is deleted by ObjectLinker) depends on
+ // RelocationFactory in TargetLDBackend
delete mBackend;
- delete mMemAreaFactory;
+ delete mBuilder;
delete mRoot;
}
enum Linker::ErrorCode Linker::extractFiles(const LinkerConfig& pConfig) {
- mLDInfo = const_cast<mcld::MCLDInfo*>(pConfig.getLDInfo());
- if (mLDInfo == NULL) {
+ mLDConfig = pConfig.getLDConfig();
+ if (mLDConfig == NULL) {
return kDelegateLDInfo;
}
-
- mRoot = new mcld::InputTree::iterator(mLDInfo->inputs().root());
- mShared = pConfig.isShared();
- mSOName = pConfig.getSOName();
-
return kSuccess;
}
enum Linker::ErrorCode Linker::config(const LinkerConfig& pConfig) {
- if (mLDInfo != NULL) {
+ if (mLDConfig != NULL) {
return kDoubleConfig;
}
extractFiles(pConfig);
- mBackend = pConfig.getTarget()->createLDBackend(pConfig.getTriple());
+ mBackend = pConfig.getTarget()->createLDBackend(*mLDConfig);
if (mBackend == NULL) {
return kCreateBackend;
}
- mMemAreaFactory = new MemoryFactory();
+ mInputFactory = new mcld::InputFactory(32, *mLDConfig);
- mDriver = new mcld::MCLDDriver(*mLDInfo, *mBackend, *mMemAreaFactory);
+ mContextFactory = new mcld::ContextFactory(32);
+ /* 32 is a magic number, the estimated number of input files **/
- mDriver->initMCLinker();
+ mMemAreaFactory = new mcld::MemoryAreaFactory(32);
+
+ mBuilder = new mcld::InputBuilder(*mLDConfig,
+ *mInputFactory,
+ *mContextFactory,
+ *mMemAreaFactory,
+ true); // delegated
+
+ mModule = new mcld::Module(mLDConfig->options().soname());
+
+ mRoot = new mcld::InputTree::iterator(mModule->getInputTree().root());
+
+ mObjLinker = new mcld::ObjectLinker(*mLDConfig, *mModule, *mBuilder, *mBackend);
+
+ mObjLinker->initFragmentLinker();
return kSuccess;
}
@@ -153,43 +173,42 @@
return pCode;
}
- mcld::LDContext *input_context = mLDInfo->contextFactory().produce(pPath);
- pInput.setContext(input_context);
+ mBuilder->setContext(pInput);
return kSuccess;
}
enum Linker::ErrorCode Linker::addNameSpec(const std::string &pNameSpec) {
- mcld::sys::fs::Path* path = NULL;
+ const mcld::sys::fs::Path* path = NULL;
// find out the real path of the namespec.
- if (mLDInfo->attrFactory().constraint().isSharedSystem()) {
+ if (mLDConfig->attribute().constraint().isSharedSystem()) {
// In the system with shared object support, we can find both archive
// and shared object.
- if (mLDInfo->attrFactory().last().isStatic()) {
+ if (mInputFactory->attr().isStatic()) {
// with --static, we must search an archive.
- path = mLDInfo->options().directories().find(pNameSpec,
- mcld::Input::Archive);
+ path = mLDConfig->options().directories().find(pNameSpec,
+ mcld::Input::Archive);
}
else {
// otherwise, with --Bdynamic, we can find either an archive or a
// shared object.
- path = mLDInfo->options().directories().find(pNameSpec,
- mcld::Input::DynObj);
+ path = mLDConfig->options().directories().find(pNameSpec,
+ mcld::Input::DynObj);
}
}
else {
// In the system without shared object support, we only look for an
// archive.
- path = mLDInfo->options().directories().find(pNameSpec,
+ path = mLDConfig->options().directories().find(pNameSpec,
mcld::Input::Archive);
}
if (NULL == path)
return kFindNameSpec;
- mcld::Input* input = mLDInfo->inputFactory().produce(pNameSpec, *path,
- mcld::Input::Unknown);
- mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
+ mcld::Input* input = mInputFactory->produce(pNameSpec, *path,
+ mcld::Input::Unknown);
+ mModule->getInputTree().insert<mcld::InputTree::Positional>(*mRoot, *input);
advanceRoot();
@@ -198,11 +217,11 @@
/// addObject - Add a object file by the filename.
enum Linker::ErrorCode Linker::addObject(const std::string &pObjectPath) {
- mcld::Input* input = mLDInfo->inputFactory().produce(pObjectPath,
- pObjectPath,
- mcld::Input::Unknown);
+ mcld::Input* input = mInputFactory->produce(pObjectPath,
+ pObjectPath,
+ mcld::Input::Unknown);
- mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
+ mModule->getInputTree().insert<mcld::InputTree::Positional>(*mRoot, *input);
advanceRoot();
@@ -212,165 +231,120 @@
/// addObject - Add a piece of memory. The memory is of ELF format.
enum Linker::ErrorCode Linker::addObject(void* pMemory, size_t pSize) {
- mcld::Input* input = mLDInfo->inputFactory().produce("memory object",
- "NAN",
- mcld::Input::Unknown);
+ mcld::Input* input = mInputFactory->produce("memory object", "NAN",
+ mcld::Input::Unknown);
- mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
+ mModule->getInputTree().insert<mcld::InputTree::Positional>(*mRoot, *input);
advanceRoot();
mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pMemory, pSize);
input->setMemArea(input_memory);
- mcld::LDContext *input_context = mLDInfo->contextFactory().produce();
+ mcld::LDContext *input_context = mContextFactory->produce();
input->setContext(input_context);
return kSuccess;
}
enum Linker::ErrorCode Linker::addCode(void* pMemory, size_t pSize) {
- mcld::Input* input = mLDInfo->inputFactory().produce("code object",
- "NAN",
- mcld::Input::External);
+ mcld::Input* input = mInputFactory->produce("code object", "NAN",
+ mcld::Input::External);
- mLDInfo->inputs().insert<mcld::InputTree::Positional>(*mRoot, *input);
+ mModule->getInputTree().insert<mcld::InputTree::Positional>(*mRoot, *input);
advanceRoot();
mcld::MemoryArea *input_memory = mMemAreaFactory->produce(pMemory, pSize);
input->setMemArea(input_memory);
- mcld::LDContext *input_context = mLDInfo->contextFactory().produce();
+ mcld::LDContext *input_context = mContextFactory->produce();
input->setContext(input_context);
- // FIXME: So far, MCLinker must set up output before add input files.
+ // FIXME: So far, FragmentLinker must set up output before add input files.
// set up LDContext
- if (mDriver->hasInitLinker()) {
+ if (mObjLinker->hasInitLinker()) {
return kNotConfig;
}
- if (!mLDInfo->output().hasContext()) {
- return kNotSetUpOutput;
- }
-
// create NULL section
- mcld::LDSection& null =
- mDriver->getLinker()->createSectHdr("",
- mcld::LDFileFormat::Null,
- llvm::ELF::SHT_NULL,
- 0);
-
- null.setSize(0);
- null.setOffset(0);
- null.setIndex(0);
- null.setInfo(0);
- null.setAlign(0);
-
- input_context->getSectionTable().push_back(&null);
+ mcld::LDSection* null = mcld::IRBuilder::CreateELFHeader(*input, "",
+ llvm::ELF::SHT_NULL, 0, 0);
+ null->setSize(0);
+ null->setOffset(0);
+ null->setInfo(0);
// create .text section
- mcld::LDSection& text = mDriver->getLinker()->createSectHdr(".text",
- mcld::LDFileFormat::Regular,
+ mcld::LDSection* text = mcld::IRBuilder::CreateELFHeader(*input, ".text",
llvm::ELF::SHT_PROGBITS,
- llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR);
+ llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
+ 1);
- text.setSize(pSize);
- text.setOffset(0x0);
- text.setIndex(1);
- text.setInfo(0);
- text.setAlign(1);
-
- input_context->getSectionTable().push_back(&text);
+ text->setSize(pSize);
+ text->setOffset(0x0);
+ text->setInfo(0);
return kSuccess;
}
enum Linker::ErrorCode Linker::setOutput(const std::string &pPath) {
- if (mLDInfo->output().hasContext()) {
- return kDoubleConfig;
- }
-
// ----- initialize output file ----- //
-
mcld::FileHandle::Permission perm = 0755;
- mcld::MemoryArea* out_area = mMemAreaFactory->produce(
+ mOutput = mMemAreaFactory->produce(
pPath,
mcld::FileHandle::ReadWrite |
mcld::FileHandle::Truncate |
mcld::FileHandle::Create,
perm);
- if (!out_area->handler()->isGood()) {
+ if (!mOutput->handler()->isGood()) {
return kOpenOutput;
}
- if (mShared) {
- mLDInfo->output().setType(mcld::Output::DynObj);
- } else {
- mLDInfo->output().setType(mcld::Output::Exec);
- }
-
- mLDInfo->output().setSOName(mSOName);
- mLDInfo->output().setMemArea(out_area);
- mLDInfo->output().setContext(mLDInfo->contextFactory().produce(pPath));
-
- // FIXME: We must initialize MCLinker before setOutput, and initialize
- // standard sections here. This is because we have to build the section
- // map before input files using it.
- if (!mDriver->hasInitLinker()) {
- return kNotConfig;
- }
-
- mDriver->initStdSections();
-
return kSuccess;
}
enum Linker::ErrorCode Linker::setOutput(int pFileHandler) {
- if (mLDInfo->output().hasContext()) {
- return kDoubleConfig;
+ mOutput = mMemAreaFactory->produce(pFileHandler, mcld::FileHandle::ReadWrite);
+
+ if (!mOutput->handler()->isGood()) {
+ return kOpenOutput;
}
- // ----- initialize output file ----- //
- mcld::MemoryArea* out_area = mMemAreaFactory->produce(pFileHandler);
-
- mLDInfo->output().setType(mcld::Output::DynObj);
- mLDInfo->output().setMemArea(out_area);
- mLDInfo->output().setContext(mLDInfo->contextFactory().produce());
-
- // FIXME: We must initialize MCLinker before setOutput, and initialize
- // standard sections here. This is because we have to build the section
- // map before input files using it.
- if (!mDriver->hasInitLinker()) {
- return kNotConfig;
- }
-
- mDriver->initStdSections();
-
return kSuccess;
}
enum Linker::ErrorCode Linker::link() {
- mDriver->normalize();
+ if (NULL == mOutput)
+ return kNotSetUpOutput;
- if (!mDriver->mergeSections()) {
- return kReadSections;
+ if (!mObjLinker->hasInitLinker()) {
+ return kNotConfig;
}
- if (!mDriver->addStandardSymbols() || !mDriver->addTargetSymbols()) {
+ mObjLinker->initStdSections();
+
+ mObjLinker->normalize();
+
+ if (!mObjLinker->readRelocations())
+ return kReadSections;
+
+ if (!mObjLinker->mergeSections())
+ return kReadSections;
+
+ if (!mObjLinker->addStandardSymbols() || !mObjLinker->addTargetSymbols()) {
return kAddAdditionalSymbols;
}
- mDriver->readRelocations();
- mDriver->prelayout();
- mDriver->layout();
- mDriver->postlayout();
- mDriver->finalizeSymbolValue();
- mDriver->relocation();
- mDriver->emitOutput();
- mDriver->postProcessing();
+ mObjLinker->scanRelocations();
+ mObjLinker->prelayout();
+ mObjLinker->layout();
+ mObjLinker->postlayout();
+ mObjLinker->finalizeSymbolValue();
+ mObjLinker->relocation();
+ mObjLinker->emitOutput(*mOutput);
+ mObjLinker->postProcessing(*mOutput);
return kSuccess;
}
diff --git a/tools/mcld/lib/Support/Initialization.cpp b/tools/mcld/lib/Support/Initialization.cpp
index 9a95f74..71bd57d 100644
--- a/tools/mcld/lib/Support/Initialization.cpp
+++ b/tools/mcld/lib/Support/Initialization.cpp
@@ -48,10 +48,10 @@
LLVMInitializeARMTargetMC();
LLVMInitializeARMTargetInfo();
LLVMInitializeARMTarget();
- LLVMInitializeARMLDTargetInfo();
- LLVMInitializeARMLDTarget();
- LLVMInitializeARMLDBackend();
- LLVMInitializeARMDiagnosticLineInfo();
+ MCLDInitializeARMLDTargetInfo();
+ MCLDInitializeARMLDTarget();
+ MCLDInitializeARMLDBackend();
+ MCLDInitializeARMDiagnosticLineInfo();
#endif
#if defined(PROVIDE_MIPS_CODEGEN)
@@ -62,10 +62,10 @@
LLVMInitializeMipsTargetMC();
LLVMInitializeMipsTargetInfo();
LLVMInitializeMipsTarget();
- LLVMInitializeMipsLDTargetInfo();
- LLVMInitializeMipsLDTarget();
- LLVMInitializeMipsLDBackend();
- LLVMInitializeMipsDiagnosticLineInfo();
+ MCLDInitializeMipsLDTargetInfo();
+ MCLDInitializeMipsLDTarget();
+ MCLDInitializeMipsLDBackend();
+ MCLDInitializeMipsDiagnosticLineInfo();
#endif
#if defined(PROVIDE_X86_CODEGEN)
@@ -76,10 +76,10 @@
LLVMInitializeX86TargetMC();
LLVMInitializeX86TargetInfo();
LLVMInitializeX86Target();
- LLVMInitializeX86LDTargetInfo();
- LLVMInitializeX86LDTarget();
- LLVMInitializeX86LDBackend();
- LLVMInitializeX86DiagnosticLineInfo();
+ MCLDInitializeX86LDTargetInfo();
+ MCLDInitializeX86LDTarget();
+ MCLDInitializeX86LDBackend();
+ MCLDInitializeX86DiagnosticLineInfo();
#endif
is_initialized = true;
diff --git a/tools/mcld/lib/Support/LinkerConfig.cpp b/tools/mcld/lib/Support/LinkerConfig.cpp
index ea30e69..3a53ae1 100644
--- a/tools/mcld/lib/Support/LinkerConfig.cpp
+++ b/tools/mcld/lib/Support/LinkerConfig.cpp
@@ -12,9 +12,9 @@
#include <llvm/Support/Signals.h>
-#include <mcld/MC/MCLDInfo.h>
-#include <mcld/MC/MCLDFile.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/MC/MCLDDirectory.h>
+#include <mcld/MC/ZOption.h>
#include <mcld/LD/TextDiagnosticPrinter.h>
#include <mcld/Support/Path.h>
#include <mcld/Support/MsgHandling.h>
@@ -23,7 +23,7 @@
using namespace alone;
LinkerConfig::LinkerConfig(const std::string &pTriple)
- : mTriple(pTriple), mShared(false), mSOName(), mTarget(NULL), mLDInfo(NULL),
+ : mTriple(pTriple), mSOName(), mTarget(NULL), mLDConfig(NULL),
mDiagLineInfo(NULL), mDiagPrinter(NULL) {
initializeTarget();
@@ -32,7 +32,7 @@
}
LinkerConfig::~LinkerConfig() {
- delete mLDInfo;
+ delete mLDConfig;
if (mDiagPrinter->getNumErrors() != 0) {
// If here, the program failed ungracefully. Run the interrupt handlers to
@@ -59,58 +59,219 @@
}
bool LinkerConfig::initializeLDInfo() {
- if (NULL != mLDInfo) {
+ if (NULL != mLDConfig) {
ALOGE("Cannot initialize mcld::MCLDInfo for given triple '%s!\n",
mTriple.c_str());
return false;
}
- mLDInfo = new mcld::MCLDInfo(getTriple(), 1, 32);
+ mLDConfig = new mcld::LinkerConfig(getTriple());
+ mLDConfig->setCodeGenType(mcld::LinkerConfig::Exec);
+
+ struct NameMap {
+ const char* from;
+ const char* to;
+ };
+
+ static const NameMap map[] =
+ {
+ {".text", ".text"},
+ {".rodata", ".rodata"},
+ {".data.rel.ro.local", ".data.rel.ro.local"},
+ {".data.rel.ro", ".data.rel.ro"},
+ {".data", ".data"},
+ {".bss", ".bss"},
+ {".tdata", ".tdata"},
+ {".tbss", ".tbss"},
+ {".init_array", ".init_array"},
+ {".fini_array", ".fini_array"},
+ // TODO: Support DT_INIT_ARRAY for all constructors?
+ {".ctors", ".ctors"},
+ {".dtors", ".dtors"},
+ // FIXME: in GNU ld, if we are creating a shared object .sdata2 and .sbss2
+ // sections would be handled differently.
+ {".sdata2", ".sdata"},
+ {".sbss2", ".sbss"},
+ {".sdata", ".sdata"},
+ {".sbss", ".sbss"},
+ {".lrodata", ".lrodata"},
+ {".ldata", ".ldata"},
+ {".lbss", ".lbss"},
+ {".gcc_except_table", ".gcc_except_table"},
+ {".gnu.linkonce.d.rel.ro.local", ".data.rel.ro.local"},
+ {".gnu.linkonce.d.rel.ro", ".data.rel.ro"},
+ {".gnu.linkonce.r", ".rodata"},
+ {".gnu.linkonce.d", ".data"},
+ {".gnu.linkonce.b", ".bss"},
+ {".gnu.linkonce.sb2", ".sbss"},
+ {".gnu.linkonce.sb", ".sbss"},
+ {".gnu.linkonce.s2", ".sdata"},
+ {".gnu.linkonce.s", ".sdata"},
+ {".gnu.linkonce.wi", ".debug_info"},
+ {".gnu.linkonce.td", ".tdata"},
+ {".gnu.linkonce.tb", ".tbss"},
+ {".gnu.linkonce.t", ".text"},
+ {".gnu.linkonce.lr", ".lrodata"},
+ {".gnu.linkonce.lb", ".lbss"},
+ {".gnu.linkonce.l", ".ldata"},
+ };
+
+ if (mLDConfig->codeGenType() != mcld::LinkerConfig::Object) {
+ const unsigned int map_size = (sizeof(map) / sizeof(map[0]) );
+ for (unsigned int i = 0; i < map_size; ++i) {
+ bool exist = false;
+ mLDConfig->scripts().sectionMap().append(map[i].from,
+ map[i].to,
+ exist);
+ }
+ }
return true;
}
bool LinkerConfig::initializeDiagnostic() {
// Set up MsgHandler.
+ mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDConfig);
+
+ mcld::InitializeDiagnosticEngine(*mLDConfig, mDiagPrinter);
+
mDiagLineInfo = mTarget->createDiagnosticLineInfo(*mTarget, mTriple);
- mDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *mLDInfo);
-
- mcld::InitializeDiagnosticEngine(*mLDInfo, mDiagLineInfo, mDiagPrinter);
-
+ mcld::getDiagnosticEngine().setLineInfo(*mDiagLineInfo);
return true;
}
+bool LinkerConfig::isShared() const {
+ return (mcld::LinkerConfig::DynObj == mLDConfig->codeGenType());
+}
+
void LinkerConfig::setShared(bool pEnable) {
- mShared = pEnable;
+ if (pEnable)
+ mLDConfig->setCodeGenType(mcld::LinkerConfig::DynObj);
+ else
+ mLDConfig->setCodeGenType(mcld::LinkerConfig::Exec);
return;
}
void LinkerConfig::setBsymbolic(bool pEnable) {
- mLDInfo->options().setBsymbolic(pEnable);
+ mLDConfig->options().setBsymbolic(pEnable);
return;
}
void LinkerConfig::setSOName(const std::string &pSOName) {
- mSOName = pSOName;
+ mLDConfig->options().setSOName(pSOName);
return;
}
void LinkerConfig::setDyld(const std::string &pDyld) {
- mLDInfo->options().setDyld(pDyld);
+ mLDConfig->options().setDyld(pDyld);
return;
}
void LinkerConfig::setSysRoot(const std::string &pSysRoot) {
- mLDInfo->options().setSysroot(mcld::sys::fs::Path(pSysRoot));
+ mLDConfig->options().setSysroot(mcld::sys::fs::Path(pSysRoot));
return;
}
+void LinkerConfig::setZOption(unsigned int pOptions) {
+ mcld::ZOption option;
+ if (pOptions & kCombReloc) {
+ option.setKind(mcld::ZOption::CombReloc);
+ mLDConfig->options().addZOption(option);
+ }
+ else {
+ option.setKind(mcld::ZOption::NoCombReloc);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kDefs) {
+ option.setKind(mcld::ZOption::Defs);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kExecStack) {
+ option.setKind(mcld::ZOption::ExecStack);
+ mLDConfig->options().addZOption(option);
+ }
+ else {
+ option.setKind(mcld::ZOption::NoExecStack);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kInitFirst) {
+ option.setKind(mcld::ZOption::InitFirst);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kInterPose) {
+ option.setKind(mcld::ZOption::InterPose);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kLoadFltr) {
+ option.setKind(mcld::ZOption::LoadFltr);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kMulDefs) {
+ option.setKind(mcld::ZOption::MulDefs);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kNoCopyReloc) {
+ option.setKind(mcld::ZOption::NoCopyReloc);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kNoDefaultLib) {
+ option.setKind(mcld::ZOption::NoDefaultLib);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kNoDelete) {
+ option.setKind(mcld::ZOption::NoDelete);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kNoDLOpen) {
+ option.setKind(mcld::ZOption::NoDLOpen);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kNoDump) {
+ option.setKind(mcld::ZOption::NoDump);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kRelro) {
+ option.setKind(mcld::ZOption::Relro);
+ mLDConfig->options().addZOption(option);
+ }
+ else {
+ option.setKind(mcld::ZOption::NoRelro);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kLazy) {
+ option.setKind(mcld::ZOption::Lazy);
+ mLDConfig->options().addZOption(option);
+ }
+ else {
+ option.setKind(mcld::ZOption::Now);
+ mLDConfig->options().addZOption(option);
+ }
+
+ if (pOptions & kOrigin) {
+ option.setKind(mcld::ZOption::Origin);
+ mLDConfig->options().addZOption(option);
+ }
+}
+
void LinkerConfig::addWrap(const std::string &pWrapSymbol) {
bool exist = false;
// Add wname -> __wrap_wname.
mcld::StringEntry<llvm::StringRef>* to_wrap =
- mLDInfo->scripts().renameMap().insert(pWrapSymbol, exist);
+ mLDConfig->scripts().renameMap().insert(pWrapSymbol, exist);
std::string to_wrap_str = "__wrap_" + pWrapSymbol;
to_wrap->setValue(to_wrap_str);
@@ -122,7 +283,7 @@
// Add __real_wname -> wname.
std::string from_real_str = "__real_" + pWrapSymbol;
mcld::StringEntry<llvm::StringRef>* from_real =
- mLDInfo->scripts().renameMap().insert(from_real_str, exist);
+ mLDConfig->scripts().renameMap().insert(from_real_str, exist);
from_real->setValue(pWrapSymbol);
if (exist) {
@@ -137,7 +298,7 @@
// Add pname -> pname_portable.
mcld::StringEntry<llvm::StringRef>* to_port =
- mLDInfo->scripts().renameMap().insert(pPortableSymbol, exist);
+ mLDConfig->scripts().renameMap().insert(pPortableSymbol, exist);
std::string to_port_str = pPortableSymbol + "_portable";
to_port->setValue(to_port_str);
@@ -149,7 +310,7 @@
// Add __real_pname -> pname.
std::string from_real_str = "__real_" + pPortableSymbol;
mcld::StringEntry<llvm::StringRef>* from_real =
- mLDInfo->scripts().renameMap().insert(from_real_str, exist);
+ mLDConfig->scripts().renameMap().insert(from_real_str, exist);
from_real->setValue(pPortableSymbol);
@@ -162,17 +323,7 @@
void LinkerConfig::addSearchDir(const std::string &pDirPath) {
// SearchDirs will remove the created MCLDDirectory.
- mcld::MCLDDirectory* sd = new mcld::MCLDDirectory(pDirPath);
-
- if (sd->isInSysroot()) {
- sd->setSysroot(mLDInfo->options().sysroot());
+ if (!mLDConfig->options().directories().insert(pDirPath)) {
+ mcld::warning(mcld::diag::warn_cannot_open_search_dir) << pDirPath;
}
-
- if (exists(sd->path()) && is_directory(sd->path())) {
- mLDInfo->options().directories().add(*sd);
- } else {
- mcld::warning(mcld::diag::warn_cannot_open_search_dir) << sd->name();
- }
-
- return;
}
diff --git a/tools/mcld/lib/Support/TargetLinkerConfigs.cpp b/tools/mcld/lib/Support/TargetLinkerConfigs.cpp
index f2ddd6f..0382c2a 100644
--- a/tools/mcld/lib/Support/TargetLinkerConfigs.cpp
+++ b/tools/mcld/lib/Support/TargetLinkerConfigs.cpp
@@ -10,6 +10,8 @@
#include "alone/Config/Config.h"
#include "alone/Support/TargetLinkerConfigs.h"
+#include <mcld/MC/InputFactory.h>
+
using namespace alone;
#ifdef TARGET_BUILD
@@ -27,21 +29,29 @@
ARMLinkerConfig::ARMLinkerConfig() : LinkerConfig(DEFAULT_ARM_TRIPLE_STRING) {
// set up target-dependent constraints of attributes
- getLDInfo()->attrFactory().constraint().enableWholeArchive();
- getLDInfo()->attrFactory().constraint().disableAsNeeded();
- getLDInfo()->attrFactory().constraint().setSharedSystem();
+ getLDConfig()->attribute().constraint().enableWholeArchive();
+ getLDConfig()->attribute().constraint().disableAsNeeded();
+ getLDConfig()->attribute().constraint().setSharedSystem();
// set up the predefined attributes
- getLDInfo()->attrFactory().predefined().setWholeArchive();
- getLDInfo()->attrFactory().predefined().setDynamic();
+ getLDConfig()->attribute().predefined().unsetWholeArchive();
+ getLDConfig()->attribute().predefined().setDynamic();
// set up target dependent options
- if (getLDInfo()->options().sysroot().empty()) {
- getLDInfo()->options().setSysroot(gDefaultSysroot);
+ if (getLDConfig()->options().sysroot().empty()) {
+ getLDConfig()->options().setSysroot(gDefaultSysroot);
}
- if (!getLDInfo()->options().hasDyld()) {
- getLDInfo()->options().setDyld(gDefaultDyld);
+ if (!getLDConfig()->options().hasDyld()) {
+ getLDConfig()->options().setDyld(gDefaultDyld);
+ }
+
+ // set up section map
+ if (getLDConfig()->codeGenType() != mcld::LinkerConfig::Object) {
+ bool exist = false;
+ getLDConfig()->scripts().sectionMap().append(".ARM.exidx", ".ARM.exidx", exist);
+ getLDConfig()->scripts().sectionMap().append(".ARM.extab", ".ARM.extab", exist);
+ getLDConfig()->scripts().sectionMap().append(".ARM.attributes", ".ARM.attributes", exist);
}
}
#endif // defined(PROVIDE_ARM_CODEGEN)
@@ -54,21 +64,21 @@
: LinkerConfig(DEFAULT_MIPS_TRIPLE_STRING) {
// set up target-dependent constraints of attibutes
- getLDInfo()->attrFactory().constraint().enableWholeArchive();
- getLDInfo()->attrFactory().constraint().disableAsNeeded();
- getLDInfo()->attrFactory().constraint().setSharedSystem();
+ getLDConfig()->attribute().constraint().enableWholeArchive();
+ getLDConfig()->attribute().constraint().disableAsNeeded();
+ getLDConfig()->attribute().constraint().setSharedSystem();
// set up the predefined attributes
- getLDInfo()->attrFactory().predefined().setWholeArchive();
- getLDInfo()->attrFactory().predefined().setDynamic();
+ getLDConfig()->attribute().predefined().unsetWholeArchive();
+ getLDConfig()->attribute().predefined().setDynamic();
// set up target dependent options
- if (getLDInfo()->options().sysroot().empty()) {
- getLDInfo()->options().setSysroot(gDefaultSysroot);
+ if (getLDConfig()->options().sysroot().empty()) {
+ getLDConfig()->options().setSysroot(gDefaultSysroot);
}
- if (!getLDInfo()->options().hasDyld()) {
- getLDInfo()->options().setDyld(gDefaultDyld);
+ if (!getLDConfig()->options().hasDyld()) {
+ getLDConfig()->options().setDyld(gDefaultDyld);
}
}
#endif // defined(PROVIDE_MIPS_CODEGEN)
@@ -80,21 +90,21 @@
X86FamilyLinkerConfigBase::X86FamilyLinkerConfigBase(const std::string& pTriple)
: LinkerConfig(pTriple) {
// set up target-dependent constraints of attibutes
- getLDInfo()->attrFactory().constraint().enableWholeArchive();
- getLDInfo()->attrFactory().constraint().disableAsNeeded();
- getLDInfo()->attrFactory().constraint().setSharedSystem();
+ getLDConfig()->attribute().constraint().enableWholeArchive();
+ getLDConfig()->attribute().constraint().disableAsNeeded();
+ getLDConfig()->attribute().constraint().setSharedSystem();
// set up the predefined attributes
- getLDInfo()->attrFactory().predefined().setWholeArchive();
- getLDInfo()->attrFactory().predefined().setDynamic();
+ getLDConfig()->attribute().predefined().unsetWholeArchive();
+ getLDConfig()->attribute().predefined().setDynamic();
// set up target dependent options
- if (getLDInfo()->options().sysroot().empty()) {
- getLDInfo()->options().setSysroot(gDefaultSysroot);
+ if (getLDConfig()->options().sysroot().empty()) {
+ getLDConfig()->options().setSysroot(gDefaultSysroot);
}
- if (!getLDInfo()->options().hasDyld()) {
- getLDInfo()->options().setDyld(gDefaultDyld);
+ if (!getLDConfig()->options().hasDyld()) {
+ getLDConfig()->options().setDyld(gDefaultDyld);
}
}
@@ -106,3 +116,29 @@
: X86FamilyLinkerConfigBase(DEFAULT_X86_64_TRIPLE_STRING) {
}
#endif // defined(PROVIDE_X86_CODEGEN)
+
+#if !defined(TARGET_BUILD)
+//===----------------------------------------------------------------------===//
+// General
+//===----------------------------------------------------------------------===//
+GeneralLinkerConfig::GeneralLinkerConfig(const std::string& pTriple)
+ : LinkerConfig(pTriple) {
+ // set up target-dependent constraints of attributes
+ getLDConfig()->attribute().constraint().enableWholeArchive();
+ getLDConfig()->attribute().constraint().disableAsNeeded();
+ getLDConfig()->attribute().constraint().setSharedSystem();
+
+ // set up the predefined attributes
+ getLDConfig()->attribute().predefined().unsetWholeArchive();
+ getLDConfig()->attribute().predefined().setDynamic();
+
+ // set up section map
+ if (llvm::Triple::arm == getLDConfig()->triple().getArch() &&
+ getLDConfig()->codeGenType() != mcld::LinkerConfig::Object) {
+ bool exist = false;
+ getLDConfig()->scripts().sectionMap().append(".ARM.exidx", ".ARM.exidx", exist);
+ getLDConfig()->scripts().sectionMap().append(".ARM.extab", ".ARM.extab", exist);
+ getLDConfig()->scripts().sectionMap().append(".ARM.attributes", ".ARM.attributes", exist);
+ }
+}
+#endif // defined(TARGET_BUILD)
diff --git a/tools/mcld/main.cpp b/tools/mcld/main.cpp
index ef525f5..a66fb7c 100644
--- a/tools/mcld/main.cpp
+++ b/tools/mcld/main.cpp
@@ -182,7 +182,7 @@
#ifdef TARGET_BUILD
config = new (std::nothrow) DefaultLinkerConfig();
#else
- config = new (std::nothrow) LinkerConfig(OptTargetTriple);
+ config = new (std::nothrow) GeneralLinkerConfig(OptTargetTriple);
#endif
if (config == NULL) {
llvm::errs() << "Out of memory when create the linker configuration!\n";
diff --git a/unittests/BinTreeTest.cpp b/unittests/BinTreeTest.cpp
index fdf2bd1..5d2cd0a 100644
--- a/unittests/BinTreeTest.cpp
+++ b/unittests/BinTreeTest.cpp
@@ -8,8 +8,8 @@
//===----------------------------------------------------------------------===//
#include "BinTreeTest.h"
-#include "mcld/ADT/TypeTraits.h"
-#include "mcld/MC/InputTree.h"
+#include <mcld/ADT/TypeTraits.h>
+#include <mcld/InputTree.h>
#include <string>
using namespace mcld;
@@ -44,8 +44,8 @@
//
-/// General
-TEST_F( BinTreeTest,Two_non_null_tree_merge)
+/// General
+TEST_F( BinTreeTest,Two_non_null_tree_merge)
{
BinaryTree<int>::iterator pos = m_pTestee->root();
m_pTestee->join<TreeIteratorBase::Rightward>(pos,0);
@@ -63,16 +63,16 @@
mergeTree->join<TreeIteratorBase::Rightward>(pos2,1);
mergeTree->join<TreeIteratorBase::Leftward>(pos2,1);
- m_pTestee->merge<TreeIteratorBase::Rightward>(pos,*mergeTree);
+ m_pTestee->merge<TreeIteratorBase::Rightward>(pos,*mergeTree);
delete mergeTree;
EXPECT_TRUE(m_pTestee->size()==8);
}
/// ---- TEST - 2 ----
-TEST_F( BinTreeTest, A_null_tree_merge_a_non_null_tree)
-{
+TEST_F( BinTreeTest, A_null_tree_merge_a_non_null_tree)
+{
BinaryTree<int>::iterator pos = m_pTestee->root();
-
+
BinaryTree<int> *mergeTree = new BinaryTree<int>;
mergeTree->join<TreeIteratorBase::Rightward>(pos,0);
--pos;
@@ -82,14 +82,14 @@
mergeTree->join<TreeIteratorBase::Rightward>(pos,2);
mergeTree->join<TreeIteratorBase::Leftward>(pos,2);
- m_pTestee->merge<TreeIteratorBase::Rightward>(pos,*mergeTree);
+ m_pTestee->merge<TreeIteratorBase::Rightward>(pos,*mergeTree);
delete mergeTree;
EXPECT_TRUE(m_pTestee->size()==5);
}
-TEST_F( BinTreeTest, A_non_null_tree_merge_a_null_tree)
-{
+TEST_F( BinTreeTest, A_non_null_tree_merge_a_null_tree)
+{
BinaryTree<int>::iterator pos = m_pTestee->root();
m_pTestee->join<TreeIteratorBase::Rightward>(pos,0);
--pos;
@@ -98,24 +98,24 @@
--pos;
m_pTestee->join<TreeIteratorBase::Rightward>(pos,2);
m_pTestee->join<TreeIteratorBase::Leftward>(pos,2);
-
+
BinaryTree<int> *mergeTree = new BinaryTree<int>;
- BinaryTree<int>::iterator pos2 = mergeTree->root();
- mergeTree->merge<TreeIteratorBase::Rightward>(pos2,*m_pTestee);
+ BinaryTree<int>::iterator pos2 = mergeTree->root();
+ mergeTree->merge<TreeIteratorBase::Rightward>(pos2,*m_pTestee);
//delete m_pTestee;
EXPECT_TRUE(mergeTree->size()==5);
delete mergeTree;
}
-TEST_F( BinTreeTest, Two_null_tree_merge)
-{
+TEST_F( BinTreeTest, Two_null_tree_merge)
+{
BinaryTree<int>::iterator pos = m_pTestee->root();
-
- BinaryTree<int> *mergeTree = new BinaryTree<int>;
- BinaryTree<int>::iterator pos2 = mergeTree->root();
- mergeTree->merge<TreeIteratorBase::Rightward>(pos2,*m_pTestee);
+ BinaryTree<int> *mergeTree = new BinaryTree<int>;
+ BinaryTree<int>::iterator pos2 = mergeTree->root();
+
+ mergeTree->merge<TreeIteratorBase::Rightward>(pos2,*m_pTestee);
//delete m_pTestee;
EXPECT_TRUE(mergeTree->size()==0);
@@ -126,7 +126,7 @@
{
int a = 111;
BinaryTree<int>::iterator pos = m_pTestee->root();
-
+
m_pTestee->join<InputTree::Inclusive>(pos,a);
pos.move<InputTree::Inclusive>();
m_pTestee->join<InputTree::Positional>(pos,10);
@@ -134,9 +134,9 @@
pos.move<InputTree::Inclusive>();
m_pTestee->join<InputTree::Positional>(pos,8);
m_pTestee->join<InputTree::Inclusive>(pos,7);
-
- BinaryTree<int>::dfs_iterator dfs_it = m_pTestee->dfs_begin();
- BinaryTree<int>::dfs_iterator dfs_end = m_pTestee->dfs_end();
+
+ BinaryTree<int>::dfs_iterator dfs_it = m_pTestee->dfs_begin();
+ BinaryTree<int>::dfs_iterator dfs_end = m_pTestee->dfs_end();
ASSERT_EQ(111, **dfs_it);
++dfs_it;
@@ -149,8 +149,8 @@
ASSERT_EQ(10, **dfs_it);
++dfs_it;
ASSERT_TRUE( dfs_it == dfs_end);
- BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
- BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
+ BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
+ BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
}
TEST_F( BinTreeTest, DFSIterator_RightMostTree)
@@ -165,9 +165,9 @@
m_pTestee->join<InputTree::Positional>(pos,3);
pos.move<InputTree::Positional>();
m_pTestee->join<InputTree::Positional>(pos,4);
-
- BinaryTree<int>::dfs_iterator dfs_it = m_pTestee->dfs_begin();
- BinaryTree<int>::dfs_iterator dfs_end = m_pTestee->dfs_end();
+
+ BinaryTree<int>::dfs_iterator dfs_it = m_pTestee->dfs_begin();
+ BinaryTree<int>::dfs_iterator dfs_end = m_pTestee->dfs_end();
ASSERT_EQ(0, **dfs_it);
++dfs_it;
@@ -187,8 +187,8 @@
{
BinaryTree<int>::iterator pos = m_pTestee->root();
m_pTestee->join<InputTree::Inclusive>(pos,0);
- BinaryTree<int>::dfs_iterator dfs_it = m_pTestee->dfs_begin();
- BinaryTree<int>::dfs_iterator dfs_end = m_pTestee->dfs_end();
+ BinaryTree<int>::dfs_iterator dfs_it = m_pTestee->dfs_begin();
+ BinaryTree<int>::dfs_iterator dfs_end = m_pTestee->dfs_end();
int counter = 0;
while( dfs_it != dfs_end ) {
++counter;
@@ -201,7 +201,7 @@
{
int a = 111;
BinaryTree<int>::iterator pos = m_pTestee->root();
-
+
m_pTestee->join<InputTree::Inclusive>(pos,a);
pos.move<InputTree::Inclusive>();
m_pTestee->join<InputTree::Positional>(pos,10);
@@ -209,9 +209,9 @@
pos.move<InputTree::Inclusive>();
m_pTestee->join<InputTree::Positional>(pos,8);
m_pTestee->join<InputTree::Inclusive>(pos,7);
-
- BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
- BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
+
+ BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
+ BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
ASSERT_EQ(111, **bfs_it);
++bfs_it;
@@ -224,8 +224,8 @@
ASSERT_EQ(7, **bfs_it);
++bfs_it;
ASSERT_TRUE(bfs_it == bfs_end);
- bfs_it = m_pTestee->bfs_begin();
- bfs_end = m_pTestee->bfs_end();
+ bfs_it = m_pTestee->bfs_begin();
+ bfs_end = m_pTestee->bfs_end();
}
TEST_F( BinTreeTest, BFSIterator_RightMostTree)
@@ -240,9 +240,9 @@
m_pTestee->join<InputTree::Positional>(pos,3);
pos.move<InputTree::Positional>();
m_pTestee->join<InputTree::Positional>(pos,4);
-
- BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
- BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
+
+ BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
+ BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
ASSERT_EQ(0, **bfs_it);
++bfs_it;
@@ -262,8 +262,8 @@
{
BinaryTree<int>::iterator pos = m_pTestee->root();
m_pTestee->join<InputTree::Inclusive>(pos,0);
- BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
- BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
+ BinaryTree<int>::bfs_iterator bfs_it = m_pTestee->bfs_begin();
+ BinaryTree<int>::bfs_iterator bfs_end = m_pTestee->bfs_end();
int counter = 0;
while( bfs_it != bfs_end ) {
++counter;
@@ -272,4 +272,40 @@
ASSERT_EQ(1, counter);
}
+TEST_F( BinTreeTest, TreeIterator)
+{
+ BinaryTree<int>::iterator pos = m_pTestee->root();
+ m_pTestee->join<InputTree::Inclusive>(pos,0);
+ pos.move<InputTree::Inclusive>();
+ m_pTestee->join<InputTree::Positional>(pos,1);
+ pos.move<InputTree::Positional>();
+ m_pTestee->join<InputTree::Inclusive>(pos,2);
+ m_pTestee->join<InputTree::Positional>(pos,5);
+ pos.move<InputTree::Inclusive>();
+ m_pTestee->join<InputTree::Positional>(pos,3);
+ pos.move<InputTree::Positional>();
+ m_pTestee->join<InputTree::Positional>(pos,4);
+
+ BinaryTree<int>::iterator it = m_pTestee->begin();
+ BinaryTree<int>::iterator end = m_pTestee->end();
+
+ ASSERT_EQ(0, **it);
+ ++it;
+ ASSERT_EQ(1, **it);
+ --it;
+ ASSERT_EQ(2, **it);
+ ++it;
+ ASSERT_EQ(3, **it);
+ ++it;
+ ASSERT_EQ(4, **it);
+ ++it;
+ ASSERT_TRUE(it == end);
+
+ it = m_pTestee->begin();
+ ++it;
+ ++it;
+ ASSERT_EQ(5, **it);
+ ++it;
+ ASSERT_TRUE(it == end);
+}
diff --git a/unittests/FileHandleTest.cpp b/unittests/FileHandleTest.cpp
index 993b07c..db6f25f 100644
--- a/unittests/FileHandleTest.cpp
+++ b/unittests/FileHandleTest.cpp
@@ -41,9 +41,7 @@
//===----------------------------------------------------------------------===//
// Testcases
-#include <iostream>
-using namespace std;
-
+//===----------------------------------------------------------------------===//
TEST_F(FileHandleTest, open_close) {
mcld::sys::fs::Path path(TOPDIR);
path.append("unittests/test.txt");
@@ -51,13 +49,13 @@
ASSERT_TRUE(m_pTestee->isOpened());
ASSERT_TRUE(m_pTestee->isGood());
- ASSERT_EQ(27, m_pTestee->size());
+ ASSERT_TRUE(27 == m_pTestee->size());
ASSERT_TRUE(m_pTestee->close());
ASSERT_FALSE(m_pTestee->isOpened());
ASSERT_TRUE(m_pTestee->isGood());
- ASSERT_EQ(0, m_pTestee->size());
+ ASSERT_TRUE(0 == m_pTestee->size());
}
TEST_F(FileHandleTest, delegate_close) {
@@ -70,13 +68,13 @@
ASSERT_TRUE(m_pTestee->isOpened());
ASSERT_TRUE(m_pTestee->isGood());
- ASSERT_EQ(27, m_pTestee->size());
+ ASSERT_TRUE(27 == m_pTestee->size());
ASSERT_TRUE(m_pTestee->close());
ASSERT_FALSE(m_pTestee->isOpened());
ASSERT_TRUE(m_pTestee->isGood());
- ASSERT_EQ(0, m_pTestee->size());
+ ASSERT_TRUE(0 == m_pTestee->size());
int close_result = ::close(fd);
int close_err = errno;
@@ -91,7 +89,7 @@
ASSERT_TRUE(m_pTestee->isOpened());
ASSERT_TRUE(m_pTestee->isGood());
- ASSERT_EQ(27, m_pTestee->size());
+ ASSERT_TRUE(27 == m_pTestee->size());
int close_result = ::close(m_pTestee->handler());
ASSERT_EQ(0, close_result);
diff --git a/unittests/FragmentRefTest.cpp b/unittests/FragmentRefTest.cpp
index d64d52b..599289d 100644
--- a/unittests/FragmentRefTest.cpp
+++ b/unittests/FragmentRefTest.cpp
@@ -8,15 +8,15 @@
//===----------------------------------------------------------------------===//
#include "FragmentRefTest.h"
-#include <mcld/LD/FragmentRef.h>
-#include <mcld/LD/RegionFragment.h>
+#include <mcld/Fragment/FragmentRef.h>
+#include <mcld/Fragment/RegionFragment.h>
#include <mcld/Support/MemoryAreaFactory.h>
#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/Path.h>
using namespace mcld;
using namespace mcld::sys::fs;
-using namespace mcld::sys::fs::detail;
using namespace mcldtest;
// Constructor can do set-up work for all test here.
@@ -50,20 +50,19 @@
MemoryRegion* region = area->request(0, 4096);
RegionFragment *frag = new RegionFragment(*region);
- FragmentRef *ref = new FragmentRef(*frag);
+ FragmentRef *ref = FragmentRef::Create(*frag, 0x0);
ASSERT_EQ('H', region->getBuffer()[0]);
- ASSERT_EQ(4096, region->size());
+ ASSERT_TRUE(4096 == region->size());
ASSERT_EQ('H', frag->getRegion().getBuffer()[0]);
- ASSERT_EQ(4096, frag->getRegion().size());
+ ASSERT_TRUE(4096 == frag->getRegion().size());
ASSERT_EQ(frag, ref->frag());
ASSERT_EQ('H', static_cast<RegionFragment*>(ref->frag())->getRegion().getBuffer()[0]);
- ASSERT_EQ(4096, static_cast<RegionFragment*>(ref->frag())->getRegion().size());
+ ASSERT_TRUE(4096 == static_cast<RegionFragment*>(ref->frag())->getRegion().size());
ASSERT_EQ('H', ref->deref()[0]);
ASSERT_TRUE(RegionFragment::classof(frag));
- delete ref;
delete frag;
delete areaFactory;
}
diff --git a/unittests/FragmentTest.cpp b/unittests/FragmentTest.cpp
index 5186ea8..9713f48 100644
--- a/unittests/FragmentTest.cpp
+++ b/unittests/FragmentTest.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
#include "FragmentTest.h"
-#include <mcld/LD/Fragment.h>
+#include <mcld/Fragment/Fragment.h>
#include <mcld/LD/SectionData.h>
#include <mcld/LD/LDSection.h>
@@ -40,40 +40,36 @@
// Testcases
TEST_F( FragmentTest, Fragment_constructor ) {
- LDSection test("test", LDFileFormat::Null, 0, 0);
- SectionData* s = new SectionData(test);
- Fragment* f1 = new Fragment(Fragment::Alignment, s);
+ LDSection* test = LDSection::Create("test", LDFileFormat::Null, 0, 0);
+ SectionData* s = SectionData::Create(*test);
+ new Fragment(Fragment::Alignment, s);
EXPECT_TRUE(1 == s->size());
- Fragment* f2 = new Fragment(Fragment::Alignment, s);
- Fragment* f3 = new Fragment(Fragment::Region, s);
- Fragment* f4 = new Fragment(Fragment::Fillment, s);
- Fragment* f5 = new Fragment(Fragment::Relocation, s);
- Fragment* f6 = new Fragment(Fragment::Target, s);
+ new Fragment(Fragment::Alignment, s);
+ new Fragment(Fragment::Region, s);
+ new Fragment(Fragment::Fillment, s);
+ new Fragment(Fragment::Relocation, s);
+ new Fragment(Fragment::Target, s);
EXPECT_TRUE(6 == s->size());
- delete s;
+ LDSection::Destroy(test);
+// SectionData::Destroy(s);
}
TEST_F( FragmentTest, Fragment_trivial_function ) {
- LDSection test("test", LDFileFormat::Null, 0, 0);
- SectionData* s = new SectionData(test);
+ LDSection* test = LDSection::Create("test", LDFileFormat::Null, 0, 0);
+ SectionData* s = SectionData::Create(*test);
Fragment* f = new Fragment(Fragment::Alignment, s);
EXPECT_TRUE(Fragment::Alignment == f->getKind());
- EXPECT_TRUE(~uint64_t(0) == f->getOffset());
- EXPECT_TRUE(~(0U) == f->getLayoutOrder());
-
f->setOffset(5566);
EXPECT_TRUE(5566 == f->getOffset());
- f->setLayoutOrder(5566);
- EXPECT_TRUE(5566 == f->getLayoutOrder());
-
//always return true
EXPECT_TRUE(f->classof(new Fragment(Fragment::Region, s)) );
- delete s;
+ LDSection::Destroy(test);
+// SectionData::Destroy(s);
}
diff --git a/unittests/GCFactoryListTraitsTest.cpp b/unittests/GCFactoryListTraitsTest.cpp
index e99d42c..db8842c 100644
--- a/unittests/GCFactoryListTraitsTest.cpp
+++ b/unittests/GCFactoryListTraitsTest.cpp
@@ -58,7 +58,7 @@
//
#define CHECK_NODE_VALUE(v_) do { \
- ASSERT_EQ(v_, it->getValue()); \
+ ASSERT_TRUE(v_ == it->getValue()); \
it++; \
} while (false)
@@ -77,26 +77,26 @@
} while (false)
TEST_F( GCFactoryListTraitsTest, Basic) {
- ASSERT_EQ(10, m_pNodeList.size());
+ ASSERT_TRUE(10 == m_pNodeList.size());
CHECK_LIST_VALUE(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
}
TEST_F( GCFactoryListTraitsTest, BasicAgain) {
- ASSERT_EQ(10, m_pNodeList.size());
+ ASSERT_TRUE(10 == m_pNodeList.size());
CHECK_LIST_VALUE(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
}
TEST_F( GCFactoryListTraitsTest, Clear) {
m_pNodeList.clear();
- ASSERT_EQ(0, m_pNodeList.size());
+ ASSERT_TRUE(0 == m_pNodeList.size());
}
TEST_F( GCFactoryListTraitsTest, PushThenPop) {
Node *NewNode = m_NodeFactory.produce(11);
m_pNodeList.push_back(NewNode);
- ASSERT_EQ(11, m_pNodeList.size());
+ ASSERT_TRUE(11 == m_pNodeList.size());
m_pNodeList.pop_back();
- ASSERT_EQ(10, m_pNodeList.size());
+ ASSERT_TRUE(10 == m_pNodeList.size());
}
TEST_F( GCFactoryListTraitsTest, CodeIterator) {
diff --git a/unittests/GCFactoryListTraitsTest.h b/unittests/GCFactoryListTraitsTest.h
index 7067907..a551848 100644
--- a/unittests/GCFactoryListTraitsTest.h
+++ b/unittests/GCFactoryListTraitsTest.h
@@ -41,10 +41,11 @@
unsigned m_Init;
unsigned m_Value;
- private:
+ public:
+ Node() : m_Init(0), m_Value(0) { }
+
Node(unsigned pInit) : m_Init(pInit), m_Value(pInit) { }
- public:
unsigned getInitialValue() const {
return m_Init;
}
diff --git a/unittests/HashTableTest.cpp b/unittests/HashTableTest.cpp
index 4106641..532c307 100644
--- a/unittests/HashTableTest.cpp
+++ b/unittests/HashTableTest.cpp
@@ -97,9 +97,9 @@
TEST_F( HashTableTest, constructor ) {
typedef HashEntry<int, int, IntCompare> HashEntryType;
HashTable<HashEntryType, IntHash, EntryFactory<HashEntryType> > hashTable(16);
- EXPECT_EQ(17, hashTable.numOfBuckets());
+ EXPECT_TRUE(17 == hashTable.numOfBuckets());
EXPECT_TRUE(hashTable.empty());
- EXPECT_EQ(0, hashTable.numOfEntries());
+ EXPECT_TRUE(0 == hashTable.numOfEntries());
}
TEST_F( HashTableTest, allocattion ) {
@@ -126,18 +126,18 @@
bool exist;
HashTableTy::entry_type* entry = 0;
- for (unsigned int key=0; key<100; ++key) {
+ for (int key=0; key<100; ++key) {
entry = hashTable->insert(key, exist);
EXPECT_FALSE(hashTable->empty());
EXPECT_FALSE(exist);
EXPECT_FALSE(NULL == entry);
- EXPECT_EQ(key, entry->key());
+ EXPECT_TRUE(key == entry->key());
entry->setValue(key+10);
}
EXPECT_FALSE(hashTable->empty());
- EXPECT_EQ(100, hashTable->numOfEntries());
- EXPECT_EQ(197, hashTable->numOfBuckets());
+ EXPECT_TRUE(100 == hashTable->numOfEntries());
+ EXPECT_TRUE(197 == hashTable->numOfBuckets());
delete hashTable;
}
@@ -179,7 +179,6 @@
hashTable->clear();
- int count;
HashTableTy::iterator iter;
for (unsigned int key=0; key<100; ++key) {
iter = hashTable->find(key);
@@ -210,7 +209,7 @@
iter = hashTable->find(key);
EXPECT_TRUE(iter == hashTable->end());
}
- EXPECT_EQ(80, hashTable->numOfEntries());
+ EXPECT_TRUE(80 == hashTable->numOfEntries());
for (unsigned int key=20; key<100; ++key) {
iter = hashTable->find(key);
@@ -220,8 +219,8 @@
for (unsigned int key=0; key<20; ++key) {
entry = hashTable->insert(key, exist);
}
- EXPECT_EQ(100, hashTable->numOfEntries());
- EXPECT_EQ(197, hashTable->numOfBuckets());
+ EXPECT_TRUE(100 == hashTable->numOfEntries());
+ EXPECT_TRUE(197 == hashTable->numOfBuckets());
delete hashTable;
}
@@ -239,7 +238,7 @@
}
HashTableTy::iterator iter;
- for (unsigned int key=0; key<400000; ++key) {
+ for (int key=0; key<400000; ++key) {
iter = hashTable->find(key);
EXPECT_EQ((key+10), iter.getEntry()->value());
}
@@ -260,7 +259,7 @@
}
HashTableTy::iterator iter, iEnd = hashTable->end();
- unsigned int counter = 0;
+ int counter = 0;
for (iter = hashTable->begin(); iter != iEnd; ++iter) {
EXPECT_EQ(iter.getEntry()->key()+10, iter.getEntry()->value());
++counter;
@@ -277,12 +276,12 @@
bool exist;
HashTableTy::entry_type* entry = 0;
- for (unsigned int key=0; key<16; ++key) {
+ for (int key=0; key<16; ++key) {
entry = hashTable->insert(key*37, exist);
entry->setValue(key+10);
}
- for (unsigned int key=0; key<16; ++key) {
- unsigned int counter = 0;
+ for (int key=0; key<16; ++key) {
+ int counter = 0;
HashTableTy::chain_iterator iter, iEnd = hashTable->end(key*37);
for (iter = hashTable->begin(key*37); iter != iEnd; ++iter) {
EXPECT_EQ(key+10, iter.getEntry()->value());
@@ -313,11 +312,11 @@
ASSERT_FALSE(exist);
entry->setValue(key);
}
- ASSERT_EQ(16, hashTable->numOfEntries());
- ASSERT_EQ(37, hashTable->numOfBuckets());
+ ASSERT_TRUE(16 == hashTable->numOfEntries());
+ ASSERT_TRUE(37 == hashTable->numOfBuckets());
unsigned int key = 0;
- unsigned int count = 0;
+ int count = 0;
HashTableTy::chain_iterator iter, iEnd = hashTable->end(key);
for (iter = hashTable->begin(key); iter != iEnd; ++iter) {
count++;
diff --git a/unittests/InputTreeTest.cpp b/unittests/InputTreeTest.cpp
index 0013601..1b1e061 100644
--- a/unittests/InputTreeTest.cpp
+++ b/unittests/InputTreeTest.cpp
@@ -6,29 +6,45 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "mcld/MC/InputTree.h"
-#include "mcld/MC/MCLDInfo.h"
-#include <InputTreeTest.h>
+#include "InputTreeTest.h"
+
+#include <vector>
+#include <iostream>
+
+#include <mcld/InputTree.h>
+#include <mcld/MC/InputFactory.h>
+#include <mcld/LinkerConfig.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/FileAction.h>
+#include <mcld/MC/CommandAction.h>
using namespace mcld;
-using namespace mcldtest;
+using namespace mcld::test;
// Constructor can do set-up work for all test here.
InputTreeTest::InputTreeTest()
-{
- // create testee. modify it if need
- m_pAttr = new mcld::AttributeFactory(2);
- m_pAlloc = new mcld::InputFactory(10, *m_pAttr);
- m_pTestee = new InputTree(*m_pAlloc);
+ : m_MemFactory(10), m_ContextFactory(4) {
+
+ // create testee. modify it if need
+ m_pConfig = new mcld::LinkerConfig("arm-none-linux-gnueabi");
+ m_pAlloc = new mcld::InputFactory(10, *m_pConfig);
+ m_pBuilder = new mcld::InputBuilder(*m_pConfig,
+ *m_pAlloc,
+ m_ContextFactory,
+ m_MemFactory,
+ false);
+ m_pTestee = new mcld::InputTree();
+ m_pBuilder->setCurrentTree(*m_pTestee);
}
// Destructor can do clean-up work that doesn't throw exceptions here.
InputTreeTest::~InputTreeTest()
{
- delete m_pTestee;
- delete m_pAlloc;
- delete m_pAttr;
+ delete m_pTestee;
+ delete m_pAlloc;
+ delete m_pBuilder;
+ delete m_pConfig;
}
// SetUp() will be called immediately before each test.
@@ -41,19 +57,33 @@
{
}
-//==========================================================================//
+//===----------------------------------------------------------------------===//
// Testcases
//
TEST_F( InputTreeTest, Basic_operation ) {
- InputTree::iterator node = m_pTestee->root();
- m_pTestee->insert<InputTree::Inclusive>(node, "FileSpec", "path1");
+ std::vector<InputAction*> actions;
+
+ size_t position = 0;
+ actions.push_back(new StartGroupAction(position++));
+ actions.push_back(new InputFileAction(position++, "path1"));
+ actions.push_back(new EndGroupAction(position++));
+
+ std::vector<InputAction*>::iterator action;
+ for (action = actions.begin(); action != actions.end(); ++action) {
+ (*action)->activate(*m_pBuilder);
+ delete *action;
+ }
+
+ InputTree::iterator node = m_pTestee->root();
InputTree::const_iterator const_node = node;
+ --node;
+ --const_node;
ASSERT_TRUE(isGroup(node));
ASSERT_TRUE(isGroup(const_node));
- ASSERT_TRUE(m_pTestee->hasInput());
- ASSERT_EQ(1, m_pTestee->numOfInputs());
+ ASSERT_FALSE(m_pAlloc->empty());
+ ASSERT_TRUE(1 == m_pAlloc->size());
--node;
@@ -65,23 +95,25 @@
ASSERT_FALSE(isGroup(node));
ASSERT_FALSE(isGroup(const_node2));
- ASSERT_TRUE(m_pTestee->hasInput());
- ASSERT_FALSE(m_pTestee->numOfInputs()==0);
+ ASSERT_FALSE(m_pAlloc->empty());
+ ASSERT_FALSE(m_pAlloc->size()==0);
- ASSERT_TRUE(m_pTestee->size()==2);
+ ASSERT_TRUE(m_pTestee->size()==3);
}
TEST_F( InputTreeTest, forLoop_TEST ) {
InputTree::iterator node = m_pTestee->root();
- m_pTestee->insert<InputTree::Inclusive>(node, "FileSpec", "path1");
+ Input* input = m_pAlloc->produce("FileSpec", "path1");
+ m_pTestee->insert<InputTree::Inclusive>(node, *input);
InputTree::const_iterator const_node = node;
--node;
for(int i=0 ; i<100 ; ++i)
{
- m_pTestee->insert<InputTree::Inclusive>(node,"FileSpec", "path1");
+ Input* input = m_pAlloc->produce("FileSpec", "path1");
+ m_pTestee->insert<InputTree::Inclusive>(node, *input);
++node;
}
@@ -90,8 +122,8 @@
ASSERT_FALSE(node.isRoot());
ASSERT_TRUE(isGroup(node));
- ASSERT_TRUE(m_pTestee->hasInput());
- ASSERT_FALSE(m_pTestee->numOfInputs()==100);
+ ASSERT_FALSE(m_pAlloc->empty());
+ ASSERT_FALSE(m_pAlloc->size()==100);
ASSERT_TRUE(m_pTestee->size()==102);
}
@@ -104,14 +136,15 @@
m_pTestee->enterGroup(node, InputTree::Downward);
--node;
- m_pTestee->insert(node, InputTree::Afterward, "FileSpec", "path1");
+ Input* input = m_pAlloc->produce("FileSpec", "path1");
+ m_pTestee->insert(node, InputTree::Afterward, *input);
++node;
}
ASSERT_FALSE(node.isRoot());
ASSERT_FALSE(isGroup(node));
- ASSERT_TRUE(m_pTestee->hasInput());
- ASSERT_TRUE(m_pTestee->numOfInputs()==50);
+ ASSERT_FALSE(m_pAlloc->empty());
+ ASSERT_TRUE(m_pAlloc->size()==50);
ASSERT_TRUE(m_pTestee->size()==100);
}
@@ -119,14 +152,19 @@
{
InputTree::iterator node = m_pTestee->root();
- m_pTestee->insert<InputTree::Inclusive>(node, "111", "/");
+ Input* input = m_pAlloc->produce("111", "/");
+ m_pTestee->insert<InputTree::Inclusive>(node, *input);
node.move<InputTree::Inclusive>();
- m_pTestee->insert<InputTree::Positional>(node, "10", "/");
+ input = m_pAlloc->produce("10", "/");
+ m_pTestee->insert<InputTree::Positional>(node, *input);
m_pTestee->enterGroup<InputTree::Inclusive>(node);
node.move<InputTree::Inclusive>();
- m_pTestee->insert<InputTree::Inclusive>(node, "7", "/");
- m_pTestee->insert<InputTree::Positional>(node, "8", "/");
+
+ input = m_pAlloc->produce("7", "/");
+ m_pTestee->insert<InputTree::Inclusive>(node, *input);
+ input = m_pAlloc->produce("8", "/");
+ m_pTestee->insert<InputTree::Positional>(node, *input);
InputTree::dfs_iterator dfs_it = m_pTestee->dfs_begin();
InputTree::dfs_iterator dfs_end = m_pTestee->dfs_end();
diff --git a/unittests/InputTreeTest.h b/unittests/InputTreeTest.h
index 2ffef9c..c0f59a7 100644
--- a/unittests/InputTreeTest.h
+++ b/unittests/InputTreeTest.h
@@ -6,21 +6,21 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef INPUTTREE_TEST_H
-#define INPUTTREE_TEST_H
+#ifndef UNITTESTS_INPUTTREE_TEST_H
+#define UNITTESTS_INPUTTREE_TEST_H
#include <gtest.h>
+#include <mcld/MC/ContextFactory.h>
+#include <mcld/Support/MemoryAreaFactory.h>
-namespace mcld
-{
+namespace mcld {
+
class InputTree;
class InputFactory;
-class AttributeFactory;
+class InputBuilder;
+class LinkerConfig;
-} // namespace for mcld
-
-namespace mcldtest
-{
+namespace test {
/** \class InputTreeTest
* \brief
@@ -30,25 +30,31 @@
class InputTreeTest : public ::testing::Test
{
public:
- // Constructor can do set-up work for all test here.
- InputTreeTest();
+ // Constructor can do set-up work for all test here.
+ InputTreeTest();
- // Destructor can do clean-up work that doesn't throw exceptions here.
- virtual ~InputTreeTest();
+ // Destructor can do clean-up work that doesn't throw exceptions here.
+ virtual ~InputTreeTest();
- // SetUp() will be called immediately before each test.
- virtual void SetUp();
+ // SetUp() will be called immediately before each test.
+ virtual void SetUp();
- // TearDown() will be called immediately after each test.
- virtual void TearDown();
+ // TearDown() will be called immediately after each test.
+ virtual void TearDown();
protected:
- mcld::AttributeFactory *m_pAttr;
- mcld::InputFactory *m_pAlloc;
- mcld::InputTree* m_pTestee;
+ mcld::LinkerConfig* m_pConfig;
+
+ mcld::InputFactory* m_pAlloc;
+ mcld::InputBuilder* m_pBuilder;
+ mcld::MemoryAreaFactory m_MemFactory;
+ mcld::ContextFactory m_ContextFactory;
+
+ mcld::InputTree* m_pTestee;
};
-} // namespace of mcldtest
+} // namespace of test
+} // namespace of mcld
#endif
diff --git a/unittests/LEB128Test.cpp b/unittests/LEB128Test.cpp
index bd1aec2..e8083b1 100644
--- a/unittests/LEB128Test.cpp
+++ b/unittests/LEB128Test.cpp
@@ -51,41 +51,41 @@
size = leb128::encode<uint32_t>(result, 2);
ASSERT_EQ(buffer[0], 2);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<uint32_t>(result, 127);
ASSERT_EQ(buffer[0], 127);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<uint32_t>(result, 128);
ASSERT_EQ(buffer[0], 0 + 0x80);
ASSERT_EQ(buffer[1], 1);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<uint32_t>(result, 129);
ASSERT_EQ(buffer[0], 1 + 0x80);
ASSERT_EQ(buffer[1], 1);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<uint32_t>(result, 130);
ASSERT_EQ(buffer[0], 2 + 0x80);
ASSERT_EQ(buffer[1], 1);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<uint32_t>(result, 12857);
ASSERT_EQ(buffer[0], 57 + 0x80);
ASSERT_EQ(buffer[1], 100);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
}
TEST_F( LEB128Test, EncodeULEB_Example_from_Dwarf3_Figure22_Using_64bits) {
@@ -97,41 +97,41 @@
size = leb128::encode<uint64_t>(result, 2);
ASSERT_EQ(buffer[0], 2);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<uint64_t>(result, 127);
ASSERT_EQ(buffer[0], 127);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<uint64_t>(result, 128);
ASSERT_EQ(buffer[0], 0 + 0x80);
ASSERT_EQ(buffer[1], 1);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<uint64_t>(result, 129);
ASSERT_EQ(buffer[0], 1 + 0x80);
ASSERT_EQ(buffer[1], 1);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<uint64_t>(result, 130);
ASSERT_EQ(buffer[0], 2 + 0x80);
ASSERT_EQ(buffer[1], 1);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<uint64_t>(result, 12857);
ASSERT_EQ(buffer[0], 57 + 0x80);
ASSERT_EQ(buffer[1], 100);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
}
TEST_F( LEB128Test, EncodeSLEB_Example_from_Dwarf3_Figure22) {
@@ -143,55 +143,55 @@
size = leb128::encode<int32_t>(result, 2);
ASSERT_EQ(buffer[0], 2);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<int32_t>(result, -2);
ASSERT_EQ(buffer[0], 0x7e);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<int32_t>(result, 127);
ASSERT_EQ(buffer[0], 127 + 0x80);
ASSERT_EQ(buffer[1], 0);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<int32_t>(result, -127);
ASSERT_EQ(buffer[0], 1 + 0x80);
ASSERT_EQ(buffer[1], 0x7f);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<int32_t>(result, 128);
ASSERT_EQ(buffer[0], 0 + 0x80);
ASSERT_EQ(buffer[1], 1);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<int32_t>(result, -128);
ASSERT_EQ(buffer[0], 0 + 0x80);
ASSERT_EQ(buffer[1], 0x7f);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<int32_t>(result, 129);
ASSERT_EQ(buffer[0], 1 + 0x80);
ASSERT_EQ(buffer[1], 1);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<int32_t>(result, -129);
ASSERT_EQ(buffer[0], 0x7f + 0x80);
ASSERT_EQ(buffer[1], 0x7e);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
}
TEST_F( LEB128Test, DecodeULEB_Example_from_Dwarf3_Figure22) {
@@ -200,33 +200,33 @@
buffer[0] = 2;
buffer[1] = 0;
- ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 2);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 2);
+ ASSERT_TRUE(size == 1);
buffer[0] = 127;
buffer[1] = 0;
- ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 127);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 127);
+ ASSERT_TRUE(size == 1);
buffer[0] = 0 + 0x80;
buffer[1] = 1;
- ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 128);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 128);
+ ASSERT_TRUE(size == 2);
buffer[0] = 1 + 0x80;
buffer[1] = 1;
- ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 129);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 129);
+ ASSERT_TRUE(size == 2);
buffer[0] = 2 + 0x80;
buffer[1] = 1;
- ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 130);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 130);
+ ASSERT_TRUE(size == 2);
buffer[0] = 57 + 0x80;
buffer[1] = 100;
- ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 12857);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 12857);
+ ASSERT_TRUE(size == 2);
}
@@ -237,42 +237,42 @@
buffer[0] = 2;
buffer[1] = 0;
ASSERT_EQ(leb128::decode<int64_t>(buffer, size), 2);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
buffer[0] = 0x7e;
buffer[1] = 0;
ASSERT_EQ(leb128::decode<int64_t>(buffer, size), -2);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
buffer[0] = 127 + 0x80;
buffer[1] = 0;
ASSERT_EQ(leb128::decode<int64_t>(buffer, size), 127);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
buffer[0] = 1 + 0x80;
buffer[1] = 0x7f;
ASSERT_EQ(leb128::decode<int64_t>(buffer, size), -127);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
buffer[0] = 0 + 0x80;
buffer[1] = 1;
ASSERT_EQ(leb128::decode<int64_t>(buffer, size), 128);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
buffer[0] = 0 + 0x80;
buffer[1] = 0x7f;
ASSERT_EQ(leb128::decode<int64_t>(buffer, size), -128);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
buffer[0] = 1 + 0x80;
buffer[1] = 1;
ASSERT_EQ(leb128::decode<int64_t>(buffer, size), 129);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
buffer[0] = 0x7f + 0x80;
buffer[1] = 0x7e;
ASSERT_EQ(leb128::decode<int64_t>(buffer, size), -129);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
}
TEST_F( LEB128Test, DecodeULEB_Tests_Found_in_Android_dalvik_dx) {
@@ -281,18 +281,18 @@
content[0] = 0;
p = content;
- ASSERT_EQ(leb128::decode<uint64_t>(p), 0);
+ ASSERT_TRUE(leb128::decode<uint64_t>(p) == 0);
ASSERT_EQ(p, content + 1);
content[0] = 1;
p = content;
- ASSERT_EQ(leb128::decode<uint64_t>(p), 1);
+ ASSERT_TRUE(leb128::decode<uint64_t>(p) == 1);
ASSERT_EQ(p, content + 1);
content[0] = 0x80;
content[1] = 0x7f;
p = content;
- ASSERT_EQ(leb128::decode<uint64_t>(p), 16256);
+ ASSERT_TRUE(leb128::decode<uint64_t>(p) == 16256);
ASSERT_EQ(p, content + 2);
}
@@ -305,67 +305,67 @@
size = leb128::encode<uint32_t>(result, 0);
ASSERT_EQ(buffer[0], 0);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<uint64_t>(result, 0);
ASSERT_EQ(buffer[0], 0);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<uint32_t>(result, 1);
ASSERT_EQ(buffer[0], 1);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<uint64_t>(result, 1);
ASSERT_EQ(buffer[0], 1);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<uint32_t>(result, 16256);
ASSERT_EQ(buffer[0], 0x80);
ASSERT_EQ(buffer[1], 0x7f);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<uint64_t>(result, 16256);
ASSERT_EQ(buffer[0], 0x80);
ASSERT_EQ(buffer[1], 0x7f);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<uint32_t>(result, 0x3b4);
ASSERT_EQ(buffer[0], 0xb4);
ASSERT_EQ(buffer[1], 0x07);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<uint64_t>(result, 0x3b4);
ASSERT_EQ(buffer[0], 0xb4);
ASSERT_EQ(buffer[1], 0x07);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<uint32_t>(result, 0x40c);
ASSERT_EQ(buffer[0], 0x8c);
ASSERT_EQ(buffer[1], 0x08);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<uint64_t>(result, 0x40c);
ASSERT_EQ(buffer[0], 0x8c);
ASSERT_EQ(buffer[1], 0x08);
ASSERT_EQ(result, buffer + 2);
- ASSERT_EQ(size, 2);
+ ASSERT_TRUE(size == 2);
result = buffer;
size = leb128::encode<uint32_t>(result, 0xffffffff);
@@ -375,7 +375,7 @@
ASSERT_EQ(buffer[3], 0xff);
ASSERT_EQ(buffer[4], 0xf);
ASSERT_EQ(result, buffer + 5);
- ASSERT_EQ(size, 5);
+ ASSERT_TRUE(size == 5);
result = buffer;
size = leb128::encode<uint64_t>(result, 0xffffffff);
@@ -385,7 +385,7 @@
ASSERT_EQ(buffer[3], 0xff);
ASSERT_EQ(buffer[4], 0xf);
ASSERT_EQ(result, buffer + 5);
- ASSERT_EQ(size, 5);
+ ASSERT_TRUE(size == 5);
}
TEST_F( LEB128Test, DecodeSLEB_Tests_Found_in_Android_dalvik_dx) {
@@ -422,45 +422,46 @@
size = leb128::encode<int32_t>(result, 0);
ASSERT_EQ(buffer[0], 0);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<int64_t>(result, 0);
ASSERT_EQ(buffer[0], 0);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<int32_t>(result, 1);
ASSERT_EQ(buffer[0], 1);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<int64_t>(result, 1);
ASSERT_EQ(buffer[0], 1);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<int32_t>(result, -1);
ASSERT_EQ(buffer[0], 0x7f);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
result = buffer;
size = leb128::encode<int64_t>(result, -1);
ASSERT_EQ(buffer[0], 0x7f);
ASSERT_EQ(result, buffer + 1);
- ASSERT_EQ(size, 1);
+ ASSERT_TRUE(size == 1);
}
TEST_F( LEB128Test, Random_Regression_Test) {
leb128::ByteType buffer[9];
for (int i = 0; i < 20; i++) {
- long int value = random();
+ unsigned long int value = random();
uint64_t value2 = value * value;
+ int64_t value3 = value * value;
leb128::ByteType *result;
size_t encode_size, decode_size;
@@ -480,16 +481,16 @@
// Test encode<uint64_t> and decode<uint64_t> on (value * value)
result = buffer;
- encode_size = leb128::encode<int64_t>(result, value2);
+ encode_size = leb128::encode<int64_t>(result, value3);
ASSERT_EQ(result, buffer + encode_size);
- ASSERT_EQ(leb128::decode<int64_t>(buffer, decode_size), value2);
+ ASSERT_EQ(leb128::decode<int64_t>(buffer, decode_size), value3);
ASSERT_EQ(encode_size, decode_size);
// Test encode<uint64_t> and decode<uint64_t> on -(value * value)
result = buffer;
- encode_size = leb128::encode<int64_t>(result, -value2);
+ encode_size = leb128::encode<int64_t>(result, -value3);
ASSERT_EQ(result, buffer + encode_size);
- ASSERT_EQ(leb128::decode<int64_t>(buffer, decode_size), -value2);
+ ASSERT_EQ(leb128::decode<int64_t>(buffer, decode_size), -value3);
ASSERT_EQ(encode_size, decode_size);
}
}
@@ -506,8 +507,8 @@
ASSERT_EQ(buffer[1], 0xb6);
ASSERT_EQ(buffer[2], 0x9);
- ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 154452);
- ASSERT_EQ(size, 3);
+ ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 154452);
+ ASSERT_TRUE(size == 3);
}
TEST_F( LEB128Test, Type_Conversion_Test) {
@@ -522,10 +523,10 @@
ASSERT_EQ(buffer[1], '\xb6');
ASSERT_EQ(buffer[2], '\x09');
- ASSERT_EQ(leb128::decode<uint64_t>(buffer, size), 154452);
- ASSERT_EQ(size, 3);
+ ASSERT_TRUE(leb128::decode<uint64_t>(buffer, size) == 154452);
+ ASSERT_TRUE(size == 3);
const char *p = buffer;
- ASSERT_EQ(leb128::decode<uint64_t>(p), 154452);
- ASSERT_EQ(p, buffer + 3);
+ ASSERT_TRUE(leb128::decode<uint64_t>(p) == 154452);
+ ASSERT_TRUE(p == (buffer + 3));
}
diff --git a/unittests/LinearAllocatorTest.cpp b/unittests/LinearAllocatorTest.cpp
index 9100160..fea135f 100644
--- a/unittests/LinearAllocatorTest.cpp
+++ b/unittests/LinearAllocatorTest.cpp
@@ -56,17 +56,17 @@
TEST_F( LinearAllocatorTest, allocateOver ) {
Data* pointer = m_pTestee->allocate(CHUNK_SIZE+1);
ASSERT_TRUE(0 == pointer);
- ASSERT_EQ(0, m_pTestee->max_size());
+ ASSERT_TRUE(0 == m_pTestee->max_size());
ASSERT_TRUE(m_pTestee->empty());
}
TEST_F( LinearAllocatorTest, alloc_construct ) {
Data* pointer = m_pTestee->allocate();
m_pTestee->construct(pointer);
- ASSERT_EQ(1, pointer->one);
- ASSERT_EQ(2, pointer->two);
- ASSERT_EQ(3, pointer->three);
- ASSERT_EQ(4, pointer->four);
+ ASSERT_TRUE(1 == pointer->one);
+ ASSERT_TRUE(2 == pointer->two);
+ ASSERT_TRUE(3 == pointer->three);
+ ASSERT_TRUE(4 == pointer->four);
}
TEST_F( LinearAllocatorTest, alloc_constructCopy ) {
@@ -74,19 +74,19 @@
Data data(7, 7, 7, 7);
m_pTestee->construct(pointer, data);
- ASSERT_EQ(7, pointer->one);
- ASSERT_EQ(7, pointer->two);
- ASSERT_EQ(7, pointer->three);
- ASSERT_EQ(7, pointer->four);
+ ASSERT_TRUE(7 == pointer->one);
+ ASSERT_TRUE(7 == pointer->two);
+ ASSERT_TRUE(7 == pointer->three);
+ ASSERT_TRUE(7 == pointer->four);
}
TEST_F( LinearAllocatorTest, allocN_construct ) {
Data* pointer = m_pTestee->allocate(10);
m_pTestee->construct(pointer);
- ASSERT_EQ(1, pointer->one);
- ASSERT_EQ(2, pointer->two);
- ASSERT_EQ(3, pointer->three);
- ASSERT_EQ(4, pointer->four);
+ ASSERT_TRUE(1 == pointer->one);
+ ASSERT_TRUE(2 == pointer->two);
+ ASSERT_TRUE(3 == pointer->three);
+ ASSERT_TRUE(4 == pointer->four);
}
TEST_F( LinearAllocatorTest, allocN_constructCopy ) {
@@ -94,10 +94,10 @@
Data data(7, 7, 7, 7);
m_pTestee->construct(pointer, data);
- ASSERT_EQ(7, pointer->one);
- ASSERT_EQ(7, pointer->two);
- ASSERT_EQ(7, pointer->three);
- ASSERT_EQ(7, pointer->four);
+ ASSERT_TRUE(7 == pointer->one);
+ ASSERT_TRUE(7 == pointer->two);
+ ASSERT_TRUE(7 == pointer->three);
+ ASSERT_TRUE(7 == pointer->four);
}
TEST_F( LinearAllocatorTest, multi_alloc_ctor_iterate ) {
diff --git a/unittests/LinearAllocatorTest.h b/unittests/LinearAllocatorTest.h
index 9e9b2ab..a6be2b7 100644
--- a/unittests/LinearAllocatorTest.h
+++ b/unittests/LinearAllocatorTest.h
@@ -63,7 +63,7 @@
virtual void TearDown();
protected:
- enum { CHUNK_SIZE = 32 };
+ enum TemplateArgsType { CHUNK_SIZE = 32 };
typedef mcld::LinearAllocator<Data, CHUNK_SIZE> Alloc;
protected:
Alloc* m_pTestee;
diff --git a/unittests/Linker/TestLinker.cpp b/unittests/Linker/TestLinker.cpp
index ad6e13a..d1ead28 100644
--- a/unittests/Linker/TestLinker.cpp
+++ b/unittests/Linker/TestLinker.cpp
@@ -8,22 +8,23 @@
//===----------------------------------------------------------------------===//
#include "TestLinker.h"
-#include <iostream>
-
#include <llvm/Support/TargetSelect.h>
+#include <mcld/Environment.h>
+#include <mcld/InputTree.h>
#include <mcld/LD/TextDiagnosticPrinter.h>
-#include <mcld/MC/InputTree.h>
+#include <mcld/MC/InputBuilder.h>
+#include <mcld/MC/InputFactory.h>
#include <mcld/MC/MCLDDirectory.h>
#include <mcld/Target/TargetLDBackend.h>
-#include <mcld/Support/RegionFactory.h>
+#include <mcld/Support/Space.h>
#include <mcld/Support/TargetSelect.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Support/raw_ostream.h>
#include <mcld/Support/SystemUtils.h>
#include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/MC/ContextFactory.h>
-using namespace std;
using namespace mcld;
using namespace mcld::sys::fs;
using namespace mcld::test;
@@ -32,9 +33,8 @@
// TestLinker
//===----------------------------------------------------------------------===//
TestLinker::TestLinker()
- : m_pTarget(NULL), m_pDriver(NULL), m_pInfo(NULL), m_pDiagLineInfo(NULL),
- m_pDiagPrinter(NULL), m_pBackend(NULL), m_pRegionFactory(NULL),
- m_pMemAreaFactory(NULL) {
+ : m_pTarget(NULL), m_pObjLinker(NULL), m_pConfig(NULL), m_pDiagLineInfo(NULL),
+ m_pDiagPrinter(NULL), m_pBackend(NULL), m_pBuilder(NULL), m_pOutput(NULL) {
}
TestLinker::~TestLinker()
@@ -47,36 +47,28 @@
for (mem = m_MemAreaList.begin(); mem != mEnd; ++mem)
delete (*mem);
- delete m_pDriver;
- delete m_pInfo;
+ delete m_pObjLinker;
+ delete m_pConfig;
delete m_pDiagLineInfo;
delete m_pDiagPrinter;
delete m_pBackend;
- delete m_pRegionFactory;
- delete m_pMemAreaFactory;
+ delete m_pBuilder;
+ delete m_pOutput;
}
bool TestLinker::initialize(const std::string &pTriple)
{
- bool is_initialized = false;
-
- if (is_initialized)
- return false;
-
// initilaize all llvm::Target and mcld::Target
llvm::InitializeAllTargets();
llvm::InitializeAllAsmPrinters();
llvm::InitializeAllAsmParsers();
llvm::InitializeAllTargetMCs();
- mcld::InitializeAllTargets();
- mcld::InitializeAllDiagnostics();
+ mcld::Initialize();
- // create mcld::MCLDInfo
- m_pInfo = new MCLDInfo(pTriple, 1, 32);
- m_Root = m_pInfo->inputs().root();
+ // create mcld::LinkerConfig
+ m_pConfig = new LinkerConfig(pTriple);
- // create mcld::RegionFactory
- m_pRegionFactory = new mcld::RegionFactory(32);
+ m_Root = m_Module.getInputTree().root();
// specify mcld::Target
std::string error;
@@ -86,64 +78,59 @@
return false;
}
- // create mcld::DiagnosticEngine
+ // create mcld::DiagnosticLineInfo
m_pDiagLineInfo = m_pTarget->createDiagnosticLineInfo(*m_pTarget, pTriple);
if (NULL == m_pDiagLineInfo) {
fatal(diag::fatal_cannot_init_lineinfo) << pTriple;
return false;
}
-
- m_pDiagPrinter = new mcld::TextDiagnosticPrinter(mcld::errs(), *m_pInfo);
-
- mcld::InitializeDiagnosticEngine(*m_pInfo, m_pDiagLineInfo, m_pDiagPrinter);
+ mcld::getDiagnosticEngine().setLineInfo(*m_pDiagLineInfo);
// create mcld::TargetLDBackend
- m_pBackend = m_pTarget->createLDBackend(pTriple);
+ m_pBackend = m_pTarget->createLDBackend(*m_pConfig);
if (NULL == m_pBackend) {
fatal(diag::fatal_cannot_init_backend) << pTriple;
return false;
}
- m_pMemAreaFactory = new MemoryAreaFactory(32);
+ m_pInputFactory = new mcld::InputFactory(10, *m_pConfig);
+ m_pContextFactory = new mcld::ContextFactory(10);
+ m_pMemAreaFactory = new mcld::MemoryAreaFactory(10);
+ m_pBuilder = new mcld::InputBuilder(*m_pConfig,
+ *m_pInputFactory,
+ *m_pContextFactory,
+ *m_pMemAreaFactory,
+ true);
- m_pDriver = new mcld::MCLDDriver(*m_pInfo, *m_pBackend, *m_pMemAreaFactory);
- m_pDriver->initMCLinker();
+ m_pObjLinker = new mcld::ObjectLinker(*m_pConfig, m_Module, *m_pBuilder, *m_pBackend);
+ m_pObjLinker->initFragmentLinker();
- is_initialized = true;
return true;
}
void TestLinker::addSearchDir(const std::string &pDirPath)
{
- assert(NULL != m_pInfo && "initialize() must be called before addSearchDir");
- assert(!m_pInfo->options().sysroot().empty() &&
+ assert(NULL != m_pConfig && "initialize() must be called before addSearchDir");
+ assert(!m_pConfig->options().sysroot().empty() &&
"must setSysRoot before addSearchDir");
- mcld::MCLDDirectory* sd = new mcld::MCLDDirectory(pDirPath);
-
- if (sd->isInSysroot()) {
- sd->setSysroot(m_pInfo->options().sysroot());
- }
-
- if (exists(sd->path()) && is_directory(sd->path())) {
- m_pInfo->options().directories().add(*sd);
- } else {
- mcld::warning(mcld::diag::warn_cannot_open_search_dir) << sd->name();
+ if (!m_pConfig->options().directories().insert(pDirPath)) {
+ mcld::warning(mcld::diag::warn_cannot_open_search_dir) << pDirPath;
}
}
void TestLinker::setSysRoot(const mcld::sys::fs::Path &pPath)
{
- assert(NULL != m_pInfo && "initialize() must be called before setSysRoot");
- m_pInfo->options().setSysroot(pPath);
+ assert(NULL != m_pConfig && "initialize() must be called before setSysRoot");
+ m_pConfig->options().setSysroot(pPath);
}
void TestLinker::addObject(const std::string &pPath)
{
- mcld::Input* input = m_pInfo->inputFactory().produce(pPath, pPath,
- mcld::Input::Unknown);
+ mcld::Input* input = m_pInputFactory->produce(pPath, pPath,
+ mcld::Input::Unknown);
- m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
+ m_Module.getInputTree().insert<mcld::InputTree::Positional>(m_Root, *input);
advanceRoot();
@@ -155,38 +142,37 @@
<< mcld::sys::strerror(handler->error());
}
- mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *handler);
+ mcld::MemoryArea* input_memory = new MemoryArea(*handler);
input->setMemArea(input_memory);
m_MemAreaList.push_back(input_memory);
- mcld::LDContext* context = m_pInfo->contextFactory().produce(pPath);
- input->setContext(context);
+ m_pBuilder->setContext(*input);
}
void TestLinker::addObject(void* pMemBuffer, size_t pSize)
{
- mcld::Input* input = m_pInfo->inputFactory().produce("memory object", "NAN",
- mcld::Input::Unknown);
+ mcld::Input* input = m_pInputFactory->produce("memory object", "NAN",
+ mcld::Input::Unknown);
- m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
+ m_Module.getInputTree().insert<mcld::InputTree::Positional>(m_Root, *input);
advanceRoot();
- mcld::Space* space = new mcld::Space(mcld::Space::EXTERNAL, pMemBuffer, pSize);
- mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *space);
+ mcld::Space* space = Space::Create(pMemBuffer, pSize);
+ mcld::MemoryArea* input_memory = new MemoryArea(*space);
input->setMemArea(input_memory);
m_MemAreaList.push_back(input_memory);
- mcld::LDContext* context = m_pInfo->contextFactory().produce();
+ mcld::LDContext* context = m_pContextFactory->produce();
input->setContext(context);
}
void TestLinker::addObject(int pFileHandler)
{
- mcld::Input* input = m_pInfo->inputFactory().produce("handler object", "NAN",
- mcld::Input::Unknown);
+ mcld::Input* input = m_pInputFactory->produce("handler object", "NAN",
+ mcld::Input::Unknown);
- m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
+ m_Module.getInputTree().insert<mcld::InputTree::Positional>(m_Root, *input);
advanceRoot();
@@ -194,11 +180,11 @@
m_FileHandleList.push_back(handler);
handler->delegate(pFileHandler);
- mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *handler);
+ mcld::MemoryArea* input_memory = new MemoryArea(*handler);
input->setMemArea(input_memory);
m_MemAreaList.push_back(input_memory);
- mcld::LDContext* context = m_pInfo->contextFactory().produce();
+ mcld::LDContext* context = m_pContextFactory->produce();
input->setContext(context);
}
@@ -206,26 +192,26 @@
{
mcld::sys::fs::Path* path = NULL;
// find out the real path of the namespec.
- if (m_pInfo->attrFactory().constraint().isSharedSystem()) {
+ if (m_pConfig->attribute().constraint().isSharedSystem()) {
// In the system with shared object support, we can find both archive
// and shared object.
- if (m_pInfo->attrFactory().last().isStatic()) {
+ if (m_pInputFactory->attr().isStatic()) {
// with --static, we must search an archive.
- path = m_pInfo->options().directories().find(pNameSpec,
- mcld::Input::Archive);
+ path = m_pConfig->options().directories().find(pNameSpec,
+ mcld::Input::Archive);
}
else {
// otherwise, with --Bdynamic, we can find either an archive or a
// shared object.
- path = m_pInfo->options().directories().find(pNameSpec,
+ path = m_pConfig->options().directories().find(pNameSpec,
mcld::Input::DynObj);
}
}
else {
// In the system without shared object support, we only look for an
// archive.
- path = m_pInfo->options().directories().find(pNameSpec,
+ path = m_pConfig->options().directories().find(pNameSpec,
mcld::Input::Archive);
}
@@ -234,10 +220,10 @@
return;
}
- mcld::Input* input = m_pInfo->inputFactory().produce(pNameSpec, *path,
- mcld::Input::Unknown);
+ mcld::Input* input = m_pInputFactory->produce(pNameSpec, *path,
+ mcld::Input::Unknown);
- m_pInfo->inputs().insert<mcld::InputTree::Positional>(m_Root, *input);
+ m_Module.getInputTree().insert<mcld::InputTree::Positional>(m_Root, *input);
advanceRoot();
@@ -249,19 +235,15 @@
<< mcld::sys::strerror(handler->error());
}
- mcld::MemoryArea* input_memory = new MemoryArea(*m_pRegionFactory, *handler);
+ mcld::MemoryArea* input_memory = new MemoryArea(*handler);
input->setMemArea(input_memory);
m_MemAreaList.push_back(input_memory);
- mcld::LDContext* context = m_pInfo->contextFactory().produce(*path);
- input->setContext(context);
+ m_pBuilder->setContext(*input);
}
bool TestLinker::setOutput(const std::string &pPath)
{
- if (m_pInfo->output().hasContext())
- return false;
-
mcld::FileHandle* handler = new mcld::FileHandle();
m_FileHandleList.push_back(handler);
bool open_res = handler->open(pPath, mcld::FileHandle::ReadWrite |
@@ -274,15 +256,10 @@
<< mcld::sys::strerror(handler->error());
}
- mcld::MemoryArea* output_memory = new MemoryArea(*m_pRegionFactory, *handler);
- m_pInfo->output().setMemArea(output_memory);
- m_MemAreaList.push_back(output_memory);
-
- mcld::LDContext* context = m_pInfo->contextFactory().produce(pPath);
- m_pInfo->output().setContext(context);
+ m_pOutput = new MemoryArea(*handler);
// FIXME: remove the initStdSections().
- m_pDriver->initStdSections();
+ m_pObjLinker->initStdSections();
return true;
}
@@ -293,22 +270,14 @@
bool TestLinker::setOutput(int pFileHandler)
{
- if (m_pInfo->output().hasContext())
- return false;
-
mcld::FileHandle* handler = new mcld::FileHandle();
handler->delegate(pFileHandler);
m_FileHandleList.push_back(handler);
- mcld::MemoryArea* output_memory = new MemoryArea(*m_pRegionFactory, *handler);
- m_pInfo->output().setMemArea(output_memory);
- m_MemAreaList.push_back(output_memory);
-
- mcld::LDContext* context = m_pInfo->contextFactory().produce();
- m_pInfo->output().setContext(context);
+ m_pOutput = new MemoryArea(*handler);
// FIXME: remove the initStdSections().
- m_pDriver->initStdSections();
+ m_pObjLinker->initStdSections();
return true;
}
diff --git a/unittests/Linker/TestLinker.h b/unittests/Linker/TestLinker.h
index f44d2b0..701a405 100644
--- a/unittests/Linker/TestLinker.h
+++ b/unittests/Linker/TestLinker.h
@@ -14,8 +14,9 @@
#include <string>
#include <list>
-#include <mcld/MC/MCLDDriver.h>
-#include <mcld/MC/MCLinker.h>
+#include <mcld/Module.h>
+#include <mcld/Object/ObjectLinker.h>
+#include <mcld/Fragment/FragmentLinker.h>
#include <mcld/LD/DiagnosticPrinter.h>
#include <mcld/LD/DiagnosticLineInfo.h>
#include <mcld/Support/TargetRegistry.h>
@@ -23,12 +24,16 @@
namespace mcld {
-class MCLDInfo;
+class FileHandle;
+class LinkerConfig;
class TargetLDBackend;
class RegionFactory;
+class InputFactory;
+class MemoryAreaFactory;
+class ContextFactory;
+class InputBuilder;
-namespace test
-{
+namespace test {
class TestLinker
{
@@ -39,16 +44,19 @@
bool initialize(const std::string &pTriple);
- MCLDInfo* config() {
- assert(NULL != m_pInfo);
- return m_pInfo;
+ LinkerConfig* config() {
+ assert(NULL != m_pConfig);
+ return m_pConfig;
}
- const MCLDInfo* config() const {
- assert(NULL != m_pInfo);
- return m_pInfo;
+ const LinkerConfig* config() const {
+ assert(NULL != m_pConfig);
+ return m_pConfig;
}
+ const Module* module() const { return &m_Module; }
+ Module* module() { return &m_Module; }
+
// ----- search directories ----- //
void addSearchDir(const std::string &pPath);
@@ -72,28 +80,32 @@
bool setOutput(const sys::fs::Path &pPath);
- /// getDriver
- MCLDDriver* getDriver() {
- assert(NULL != m_pDriver);
- return m_pDriver;
+ const MemoryArea* getOutput() const { return m_pOutput; }
+
+ MemoryArea* getOutput() { return m_pOutput; }
+
+ /// getObjLinker
+ ObjectLinker* getObjLinker() {
+ assert(NULL != m_pObjLinker);
+ return m_pObjLinker;
}
- /// getDriver
- const MCLDDriver* getDriver() const {
- assert(NULL != m_pDriver);
- return m_pDriver;
+ /// getObjLinker
+ const ObjectLinker* getObjLinker() const {
+ assert(NULL != m_pObjLinker);
+ return m_pObjLinker;
}
/// getLinker
- MCLinker* getLinker() {
- assert(NULL != m_pDriver);
- return m_pDriver->getLinker();
+ FragmentLinker* getLinker() {
+ assert(NULL != m_pObjLinker);
+ return m_pObjLinker->getLinker();
}
/// getLinker
- const MCLinker* getLinker() const {
- assert(NULL != m_pDriver);
- return m_pDriver->getLinker();
+ const FragmentLinker* getLinker() const {
+ assert(NULL != m_pObjLinker);
+ return m_pObjLinker->getLinker();
}
private:
@@ -101,21 +113,27 @@
private:
const mcld::Target* m_pTarget;
- mcld::MCLDDriver *m_pDriver;
- mcld::MCLDInfo* m_pInfo;
+ mcld::ObjectLinker *m_pObjLinker;
+ mcld::LinkerConfig* m_pConfig;
+ mcld::Module m_Module;
mcld::DiagnosticLineInfo* m_pDiagLineInfo;
mcld::DiagnosticPrinter* m_pDiagPrinter;
mcld::TargetLDBackend* m_pBackend;
mcld::InputTree::iterator m_Root;
- mcld::RegionFactory* m_pRegionFactory;
+ mcld::InputFactory* m_pInputFactory;
mcld::MemoryAreaFactory* m_pMemAreaFactory;
+ mcld::ContextFactory* m_pContextFactory;
+
+ mcld::InputBuilder* m_pBuilder;
std::list<mcld::FileHandle*> m_FileHandleList;
std::list<mcld::MemoryArea*> m_MemAreaList;
+ mcld::MemoryArea* m_pOutput;
};
} // namespace of test
} // namespace of mcld
+
#endif
diff --git a/unittests/LinkerTest.cpp b/unittests/LinkerTest.cpp
new file mode 100644
index 0000000..64da08d
--- /dev/null
+++ b/unittests/LinkerTest.cpp
@@ -0,0 +1,415 @@
+//===- LinkerTest.cpp -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "LinkerTest.h"
+
+#include <mcld/Environment.h>
+#include <mcld/Module.h>
+#include <mcld/InputTree.h>
+#include <mcld/IRBuilder.h>
+#include <mcld/Linker.h>
+#include <mcld/LinkerConfig.h>
+
+#include <mcld/Support/Path.h>
+
+#include <llvm/Support/ELF.h>
+
+using namespace mcld;
+using namespace mcld::test;
+using namespace mcld::sys::fs;
+
+
+// Constructor can do set-up work for all test here.
+LinkerTest::LinkerTest()
+{
+}
+
+// Destructor can do clean-up work that doesn't throw exceptions here.
+LinkerTest::~LinkerTest()
+{
+}
+
+// SetUp() will be called immediately before each test.
+void LinkerTest::SetUp()
+{
+}
+
+// TearDown() will be called immediately after each test.
+void LinkerTest::TearDown()
+{
+}
+
+//===----------------------------------------------------------------------===//
+// Testcases
+//===----------------------------------------------------------------------===//
+TEST_F( LinkerTest, set_up_n_clean_up) {
+
+ Initialize();
+ LinkerConfig config("arm-none-linux-gnueabi");
+
+ Module module("test");
+ config.setCodeGenType(LinkerConfig::DynObj);
+
+ Linker linker;
+ linker.config(config);
+
+ IRBuilder builder(module, config);
+ // create inputs here
+ // builder.CreateInput("./test.o");
+
+ if (linker.link(module, builder))
+ linker.emit("./test.so");
+
+ Finalize();
+}
+
+// %MCLinker --shared -soname=libplasma.so -Bsymbolic
+// -mtriple="armv7-none-linux-gnueabi"
+// -L=%p/../../../libs/ARM/Android/android-14
+// %p/../../../libs/ARM/Android/android-14/crtbegin_so.o
+// %p/plasma.o
+// -lm -llog -ljnigraphics -lc
+// %p/../../../libs/ARM/Android/android-14/crtend_so.o
+// -o libplasma.so
+TEST_F( LinkerTest, plasma) {
+
+ Initialize();
+ Linker linker;
+
+ ///< --mtriple="armv7-none-linux-gnueabi"
+ LinkerConfig config("armv7-none-linux-gnueabi");
+
+ /// To configure linker before setting options. Linker::config sets up
+ /// default target-dependent configuration to LinkerConfig.
+ linker.config(config);
+
+ config.setCodeGenType(LinkerConfig::DynObj); ///< --shared
+ config.options().setSOName("libplasma.so"); ///< --soname=libplasma.so
+ config.options().setBsymbolic(); ///< -Bsymbolic
+
+ /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+ Path search_dir(TOPDIR);
+ search_dir.append("test/libs/ARM/Android/android-14");
+ config.options().directories().insert(search_dir);
+
+ Module module("libplasma.so");
+ IRBuilder builder(module, config);
+
+ /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtbegin_so.o
+ Path crtbegin(search_dir);
+ crtbegin.append("crtbegin_so.o");
+ builder.ReadInput("crtbegin", crtbegin);
+
+ /// ${TOPDIR}/test/Android/Plasma/ARM/plasma.o
+ Path plasma(TOPDIR);
+ plasma.append("test/Android/Plasma/ARM/plasma.o");
+ builder.ReadInput("plasma", plasma);
+
+ // -lm -llog -ljnigraphics -lc
+ builder.ReadInput("m");
+ builder.ReadInput("log");
+ builder.ReadInput("jnigraphics");
+ builder.ReadInput("c");
+
+ /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtend_so.o
+ Path crtend(search_dir);
+ crtend.append("crtend_so.o");
+ builder.ReadInput("crtend", crtend);
+
+ if (linker.link(module, builder)) {
+ linker.emit("libplasma.so"); ///< -o libplasma.so
+ }
+
+ Finalize();
+}
+
+// The outputs generated without -Bsymbolic usually have more relocation
+// entries than the outputs generated with -Bsymbolic. This testcase generates
+// output with -Bsymbolic first, then generate the same output without -Bsymbolic.
+// By this way, we can make sure symbols and relocations are cleaned between
+// two linkings.
+TEST_F( LinkerTest, plasma_twice) {
+
+ Initialize();
+ Linker linker;
+
+ ///< --mtriple="armv7-none-linux-gnueabi"
+ LinkerConfig config1("armv7-none-linux-gnueabi");
+
+ /// To configure linker before setting options. Linker::config sets up
+ /// default target-dependent configuration to LinkerConfig.
+ linker.config(config1);
+
+ config1.setCodeGenType(LinkerConfig::DynObj); ///< --shared
+ config1.options().setSOName("libplasma.once.so"); ///< --soname=libplasma.twice.so
+ config1.options().setBsymbolic(false); ///< -Bsymbolic
+
+ /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+ Path search_dir(TOPDIR);
+ search_dir.append("test/libs/ARM/Android/android-14");
+ config1.options().directories().insert(search_dir);
+
+ Module module1("libplasma.once.so");
+ IRBuilder builder1(module1, config1);
+
+ /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtbegin_so.o
+ Path crtbegin(search_dir);
+ crtbegin.append("crtbegin_so.o");
+ builder1.ReadInput("crtbegin", crtbegin);
+
+ /// ${TOPDIR}/test/Android/Plasma/ARM/plasma.o
+ Path plasma(TOPDIR);
+ plasma.append("test/Android/Plasma/ARM/plasma.o");
+ builder1.ReadInput("plasma", plasma);
+
+ // -lm -llog -ljnigraphics -lc
+ builder1.ReadInput("m");
+ builder1.ReadInput("log");
+ builder1.ReadInput("jnigraphics");
+ builder1.ReadInput("c");
+
+ /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtend_so.o
+ Path crtend(search_dir);
+ crtend.append("crtend_so.o");
+ builder1.ReadInput("crtend", crtend);
+
+ if (linker.link(module1, builder1)) {
+ linker.emit("libplasma.once.so"); ///< -o libplasma.so
+ }
+
+ Finalize();
+
+ linker.reset();
+
+ Initialize();
+
+ ///< --mtriple="armv7-none-linux-gnueabi"
+ LinkerConfig config2("armv7-none-linux-gnueabi");
+
+ /// To configure linker before setting options. Linker::config sets up
+ /// default target-dependent configuration to LinkerConfig.
+ linker.config(config2);
+
+ config2.setCodeGenType(LinkerConfig::DynObj); ///< --shared
+ config2.options().setSOName("libplasma.twice.so"); ///< --soname=libplasma.twice.exe
+ config2.options().setBsymbolic(); ///< -Bsymbolic
+
+ /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+ config2.options().directories().insert(search_dir);
+
+ Module module2("libplasma.so");
+ IRBuilder builder2(module2, config2);
+
+ /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtbegin_so.o
+ builder2.ReadInput("crtbegin", crtbegin);
+
+ /// ${TOPDIR}/test/Android/Plasma/ARM/plasma.o
+ builder2.ReadInput("plasma", plasma);
+
+ // -lm -llog -ljnigraphics -lc
+ builder2.ReadInput("m");
+ builder2.ReadInput("log");
+ builder2.ReadInput("jnigraphics");
+ builder2.ReadInput("c");
+
+ /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtend_so.o
+ builder2.ReadInput("crtend", crtend);
+
+ if (linker.link(module2, builder2)) {
+ linker.emit("libplasma.twice.so"); ///< -o libplasma.exe
+ }
+
+ Finalize();
+}
+
+// This testcase put IRBuilder in the heap
+TEST_F( LinkerTest, plasma_twice_irbuilder_heap) {
+
+ Initialize();
+ Linker linker;
+
+ ///< --mtriple="armv7-none-linux-gnueabi"
+ LinkerConfig config1("armv7-none-linux-gnueabi");
+
+ /// To configure linker before setting options. Linker::config sets up
+ /// default target-dependent configuration to LinkerConfig.
+ linker.config(config1);
+
+ config1.setCodeGenType(LinkerConfig::DynObj); ///< --shared
+ config1.options().setSOName("libplasma.once.so"); ///< --soname=libplasma.twice.so
+ config1.options().setBsymbolic(false); ///< -Bsymbolic
+
+ /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+ Path search_dir(TOPDIR);
+ search_dir.append("test/libs/ARM/Android/android-14");
+ config1.options().directories().insert(search_dir);
+
+ Module module1("libplasma.once.so");
+ IRBuilder *builder1 = new IRBuilder(module1, config1);
+
+ /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtbegin_so.o
+ Path crtbegin(search_dir);
+ crtbegin.append("crtbegin_so.o");
+ builder1->ReadInput("crtbegin", crtbegin);
+
+ /// ${TOPDIR}/test/Android/Plasma/ARM/plasma.o
+ Path plasma(TOPDIR);
+ plasma.append("test/Android/Plasma/ARM/plasma.o");
+ builder1->ReadInput("plasma", plasma);
+
+ // -lm -llog -ljnigraphics -lc
+ builder1->ReadInput("m");
+ builder1->ReadInput("log");
+ builder1->ReadInput("jnigraphics");
+ builder1->ReadInput("c");
+
+ /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtend_so.o
+ Path crtend(search_dir);
+ crtend.append("crtend_so.o");
+ builder1->ReadInput("crtend", crtend);
+
+ if (linker.link(module1, *builder1)) {
+ linker.emit("libplasma.once.so"); ///< -o libplasma.so
+ }
+
+ // Can not delete builder until emit the output. Dynamic string table
+ // needs the file name of the input files, and the inputs' life is
+ // controlled by IRBuilder
+ delete builder1;
+
+ Finalize();
+
+ linker.reset();
+
+ Initialize();
+
+ ///< --mtriple="armv7-none-linux-gnueabi"
+ LinkerConfig config2("armv7-none-linux-gnueabi");
+
+ /// To configure linker before setting options. Linker::config sets up
+ /// default target-dependent configuration to LinkerConfig.
+ linker.config(config2);
+
+ config2.setCodeGenType(LinkerConfig::DynObj); ///< --shared
+ config2.options().setSOName("libplasma.twice.so"); ///< --soname=libplasma.twice.exe
+ config2.options().setBsymbolic(); ///< -Bsymbolic
+
+ /// -L=${TOPDIR}/test/libs/ARM/Android/android-14
+ config2.options().directories().insert(search_dir);
+
+ Module module2("libplasma.so");
+ IRBuilder* builder2 = new IRBuilder(module2, config2);
+
+ /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtbegin_so.o
+ builder2->ReadInput("crtbegin", crtbegin);
+
+ /// ${TOPDIR}/test/Android/Plasma/ARM/plasma.o
+ builder2->ReadInput("plasma", plasma);
+
+ // -lm -llog -ljnigraphics -lc
+ builder2->ReadInput("m");
+ builder2->ReadInput("log");
+ builder2->ReadInput("jnigraphics");
+ builder2->ReadInput("c");
+
+ /// ${TOPDIR}/test/libs/ARM/Android/android-14/crtend_so.o
+ builder2->ReadInput("crtend", crtend);
+
+ if (linker.link(module2, *builder2)) {
+ linker.emit("libplasma.twice.so"); ///< -o libplasma.exe
+ }
+
+ delete builder2;
+ Finalize();
+}
+
+// %MCLinker --shared -soname=libgotplt.so -mtriple arm-none-linux-gnueabi
+// gotplt.o -o libgotplt.so
+TEST_F( LinkerTest, plasma_object) {
+
+ Initialize();
+ Linker linker;
+
+ ///< --mtriple="armv7-none-linux-gnueabi"
+ LinkerConfig config("armv7-none-linux-gnueabi");
+
+ /// To configure linker before setting options. Linker::config sets up
+ /// default target-dependent configuration to LinkerConfig.
+ linker.config(config);
+
+ config.setCodeGenType(LinkerConfig::DynObj); ///< --shared
+ config.options().setSOName("libgotplt.so"); ///< --soname=libgotplt.so
+
+ Module module;
+ IRBuilder builder(module, config);
+
+ Path gotplt_o(TOPDIR);
+ gotplt_o.append("test/PLT/gotplt.o");
+ Input* input = builder.CreateInput("gotplt.o", gotplt_o, Input::Object);
+
+ /// [ 0] NULL 00000000 000000 000000 00 0 0 0
+ builder.CreateELFHeader(*input,
+ "",
+ LDFileFormat::Null,
+ llvm::ELF::SHT_NULL,
+ 0x0);
+
+ /// [ 1] .text PROGBITS 00000000 000034 000010 00 AX 0 0 4
+ LDSection* text = builder.CreateELFHeader(*input,
+ ".text",
+ llvm::ELF::SHT_PROGBITS,
+ llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR,
+ 4);
+
+ SectionData* text_data = builder.CreateSectionData(*text);
+ static uint8_t text_content[] = { 0x00, 0x48, 0x2d, 0xe9,
+ 0xfe, 0xff, 0xff, 0xeb,
+ 0x00, 0x48, 0xbd, 0xe8,
+ 0x0e, 0xf0, 0xa0, 0xe1 };
+ Fragment* text_frag = builder.CreateRegion(text_content, 0x10);
+ builder.AppendFragment(*text_frag, *text_data);
+
+ // [ 3] .data PROGBITS 00000000 000044 000000 00 WA 0 0 4
+ builder.CreateELFHeader(*input,
+ ".data",
+ llvm::ELF::SHT_PROGBITS,
+ llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
+ 4);
+
+ // [ 4] .bss NOBITS 00000000 000044 000000 00 WA 0 0 4
+ builder.CreateELFHeader(*input,
+ ".bss",
+ llvm::ELF::SHT_PROGBITS,
+ llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE,
+ 4);
+ // [ 5] .ARM.attributes ARM_ATTRIBUTES 00000000 000044 000020 00 0 0 1
+ LDSection* attr = builder.CreateELFHeader(*input,
+ ".ARM.attributes",
+ llvm::ELF::SHT_ARM_ATTRIBUTES,
+ 0x0,
+ 4);
+
+ SectionData* attr_data = builder.CreateSectionData(*attr);
+ static uint8_t attr_content[] = {
+ 0x41, 0x1f, 0x00, 0x00,
+ 0x00, 0x61, 0x65, 0x61,
+ 0x62, 0x69, 0x00, 0x01,
+ 0x15, 0x00, 0x00, 0x00,
+ 0x06, 0x02, 0x08, 0x01,
+ 0x09, 0x01, 0x14, 0x01,
+ 0x15, 0x01, 0x17, 0x03,
+ 0x18, 0x01, 0x19, 0x01 };
+ Fragment* attr_frag = builder.CreateRegion(attr_content, 0x20);
+ builder.AppendFragment(*attr_frag, *attr_data);
+
+ if (linker.link(module, builder)) {
+ linker.emit("libgotplt.so"); ///< -o libgotplt.so
+ }
+
+ Finalize();
+}
diff --git a/unittests/LinkerTest.h b/unittests/LinkerTest.h
new file mode 100644
index 0000000..cb60d40
--- /dev/null
+++ b/unittests/LinkerTest.h
@@ -0,0 +1,40 @@
+//===- LinkerTest.h -------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef MCLD_LINKER_TEST_H
+#define MCLD_LINKER_TEST_H
+
+#include <gtest.h>
+
+namespace mcld {
+
+class Linker;
+
+namespace test {
+
+class LinkerTest : public ::testing::Test
+{
+public:
+ // Constructor can do set-up work for all test here.
+ LinkerTest();
+
+ // Destructor can do clean-up work that doesn't throw exceptions here.
+ virtual ~LinkerTest();
+
+ // SetUp() will be called immediately before each test.
+ virtual void SetUp();
+
+ // TearDown() will be called immediately after each test.
+ virtual void TearDown();
+};
+
+} // namespace of test
+} // namespace for mcld
+
+#endif
+
diff --git a/unittests/PathTest.cpp b/unittests/PathTest.cpp
index 2a4de80..2a44368 100644
--- a/unittests/PathTest.cpp
+++ b/unittests/PathTest.cpp
@@ -155,3 +155,13 @@
EXPECT_TRUE(m_pTestee->parent_path().empty());
}
+TEST_F(PathTest, filename) {
+ m_pTestee->assign("aa/bb/cc");
+ EXPECT_STREQ("cc", m_pTestee->filename().c_str());
+
+ m_pTestee->assign("aa/bb/");
+ EXPECT_STREQ("", m_pTestee->filename().c_str());
+
+ m_pTestee->assign("aa");
+ EXPECT_STREQ("aa", m_pTestee->filename().c_str());
+}
diff --git a/unittests/RTLinearAllocatorTest.cpp b/unittests/RTLinearAllocatorTest.cpp
index 9ef31e5..7ed5dac 100644
--- a/unittests/RTLinearAllocatorTest.cpp
+++ b/unittests/RTLinearAllocatorTest.cpp
@@ -43,31 +43,31 @@
TEST_F(RTLinearAllocatorTest, AllocateN) {
Data* pointer = m_pTestee->allocate(10);
ASSERT_FALSE(0 == pointer);
- ASSERT_EQ(CHUNK_SIZE, m_pTestee->max_size());
+ ASSERT_TRUE(CHUNK_SIZE == m_pTestee->max_size());
ASSERT_FALSE(m_pTestee->empty());
}
TEST_F(RTLinearAllocatorTest, allocate ) {
Data* pointer = m_pTestee->allocate();
ASSERT_FALSE(0 == pointer);
- ASSERT_EQ(CHUNK_SIZE, m_pTestee->max_size());
+ ASSERT_TRUE(CHUNK_SIZE == m_pTestee->max_size());
ASSERT_FALSE(m_pTestee->empty());
}
TEST_F(RTLinearAllocatorTest, allocateOver ) {
Data* pointer = m_pTestee->allocate(CHUNK_SIZE+1);
ASSERT_TRUE(0 == pointer);
- ASSERT_EQ(0, m_pTestee->max_size());
+ ASSERT_TRUE(0 == m_pTestee->max_size());
ASSERT_TRUE(m_pTestee->empty());
}
TEST_F(RTLinearAllocatorTest, alloc_construct ) {
Data* pointer = m_pTestee->allocate();
m_pTestee->construct(pointer);
- ASSERT_EQ(1, pointer->one);
- ASSERT_EQ(2, pointer->two);
- ASSERT_EQ(3, pointer->three);
- ASSERT_EQ(4, pointer->four);
+ ASSERT_TRUE(1 == pointer->one);
+ ASSERT_TRUE(2 == pointer->two);
+ ASSERT_TRUE(3 == pointer->three);
+ ASSERT_TRUE(4 == pointer->four);
}
TEST_F(RTLinearAllocatorTest, alloc_constructCopy ) {
@@ -75,19 +75,19 @@
Data data(7, 7, 7, 7);
m_pTestee->construct(pointer, data);
- ASSERT_EQ(7, pointer->one);
- ASSERT_EQ(7, pointer->two);
- ASSERT_EQ(7, pointer->three);
- ASSERT_EQ(7, pointer->four);
+ ASSERT_TRUE(7 == pointer->one);
+ ASSERT_TRUE(7 == pointer->two);
+ ASSERT_TRUE(7 == pointer->three);
+ ASSERT_TRUE(7 == pointer->four);
}
TEST_F(RTLinearAllocatorTest, allocN_construct ) {
Data* pointer = m_pTestee->allocate(10);
m_pTestee->construct(pointer);
- ASSERT_EQ(1, pointer->one);
- ASSERT_EQ(2, pointer->two);
- ASSERT_EQ(3, pointer->three);
- ASSERT_EQ(4, pointer->four);
+ ASSERT_TRUE(1 == pointer->one);
+ ASSERT_TRUE(2 == pointer->two);
+ ASSERT_TRUE(3 == pointer->three);
+ ASSERT_TRUE(4 == pointer->four);
}
TEST_F(RTLinearAllocatorTest, allocN_constructCopy ) {
@@ -95,10 +95,10 @@
Data data(7, 7, 7, 7);
m_pTestee->construct(pointer, data);
- ASSERT_EQ(7, pointer->one);
- ASSERT_EQ(7, pointer->two);
- ASSERT_EQ(7, pointer->three);
- ASSERT_EQ(7, pointer->four);
+ ASSERT_TRUE(7 == pointer->one);
+ ASSERT_TRUE(7 == pointer->two);
+ ASSERT_TRUE(7 == pointer->three);
+ ASSERT_TRUE(7 == pointer->four);
}
TEST_F(RTLinearAllocatorTest, multi_alloc_ctor_iterate ) {
diff --git a/unittests/ReadStageTest.cpp b/unittests/ReadStageTest.cpp
index c687c0b..b2aaf8d 100644
--- a/unittests/ReadStageTest.cpp
+++ b/unittests/ReadStageTest.cpp
@@ -7,13 +7,17 @@
//
//===----------------------------------------------------------------------===//
#include "ReadStageTest.h"
+
+#include <mcld/Module.h>
#include <mcld/LD/LDContext.h>
#include <mcld/LD/LDSection.h>
#include <mcld/LD/SectionData.h>
-#include <mcld/LD/Fragment.h>
-#include <mcld/LD/FragmentRef.h>
+#include <mcld/Fragment/Fragment.h>
+#include <mcld/Fragment/FragmentRef.h>
#include <mcld/LD/LDSymbol.h>
#include <mcld/LD/ResolveInfo.h>
+#include <mcld/MC/InputFactory.h>
+#include <mcld/Support/FileHandle.h>
#include <sstream>
#include <iostream>
@@ -41,13 +45,13 @@
m_pLinker->initialize("arm-none-linux-gnueabi");
// set up target-dependent constraints of attributes
- m_pLinker->config()->attrFactory().constraint().enableWholeArchive();
- m_pLinker->config()->attrFactory().constraint().disableAsNeeded();
- m_pLinker->config()->attrFactory().constraint().setSharedSystem();
+ m_pLinker->config()->attribute().constraint().enableWholeArchive();
+ m_pLinker->config()->attribute().constraint().disableAsNeeded();
+ m_pLinker->config()->attribute().constraint().setSharedSystem();
// set up the predefined attributes
- m_pLinker->config()->attrFactory().predefined().setWholeArchive();
- m_pLinker->config()->attrFactory().predefined().setDynamic();
+ m_pLinker->config()->attribute().predefined().setWholeArchive();
+ m_pLinker->config()->attribute().predefined().setDynamic();
// set up target dependent options
mcld::sys::fs::Path path = TOPDIR;
@@ -68,17 +72,17 @@
void ReadStageTest::dumpInput(const mcld::Input &pInput, mcld::FileHandle &pFile, size_t pIdent)
{
stringstream sstream;
- for (int i=0; i < pIdent; ++i)
+ for (size_t i=0; i < pIdent; ++i)
sstream << " ";
sstream << "<input name=\"" << pInput.name() << "\">\n";
LDContext::const_sect_iterator sect, sectEnd = pInput.context()->sectEnd();
for (sect = pInput.context()->sectBegin(); sect != sectEnd; ++sect) {
- for (int i=0; i < (pIdent+1); ++i)
+ for (size_t i=0; i < (pIdent+1); ++i)
sstream << " ";
sstream << "<section name=\"" << (*sect)->name() << "\"/>\n";
}
- for (int i=0; i < pIdent; ++i)
+ for (size_t i=0; i < pIdent; ++i)
sstream << " ";
sstream << "</input>\n";
@@ -87,20 +91,20 @@
pFile.write(sstream.str().data(), org_size, sstream.str().size());
}
-void ReadStageTest::dumpOutput(const mcld::Output &pOutput, mcld::FileHandle &pFile, size_t pIdent)
+void ReadStageTest::dumpOutput(const mcld::Module& pModule, mcld::FileHandle &pFile, size_t pIdent)
{
stringstream sstream;
- for (int i=0; i < pIdent; ++i)
+ for (size_t i=0; i < pIdent; ++i)
sstream << " ";
- sstream << "<output name=\"" << pOutput.name() << "\">\n";
+ sstream << "<output name=\"" << m_pLinker->module()->name() << "\">\n";
- LDContext::const_sect_iterator sect, sectEnd = pOutput.context()->sectEnd();
- for (sect = pOutput.context()->sectBegin(); sect != sectEnd; ++sect) {
- for (int i=0; i < (pIdent+1); ++i)
+ Module::const_iterator sect, sectEnd = pModule.end();
+ for (sect = pModule.begin(); sect != sectEnd; ++sect) {
+ for (size_t i=0; i < (pIdent+1); ++i)
sstream << " ";
sstream << "<section name=\"" << (*sect)->name() << "\"/>\n";
}
- for (int i=0; i < pIdent; ++i)
+ for (size_t i=0; i < pIdent; ++i)
sstream << " ";
sstream << "</output>\n";
@@ -115,7 +119,7 @@
mcld::sys::fs::Path top_level = TOPDIR;
// set up output
- m_pLinker->config()->output().setType(mcld::Output::DynObj);
+ m_pLinker->config()->setCodeGenType(mcld::LinkerConfig::DynObj);
m_pLinker->setOutput(top_level + "unittests/plasma.so");
@@ -129,19 +133,19 @@
m_pLinker->addObject(top_level + "test/libs/ARM/Android/android-14/crtend_so.o");
// dump status
- m_pLinker->getDriver()->normalize();
+ m_pLinker->getObjLinker()->normalize();
FileHandle file;
file.open(top_level + "unittests/read_stage.xml",
FileHandle::ReadWrite | FileHandle::Create | FileHandle::Truncate, 0644);
- InputTree::iterator input, inEnd = m_pLinker->config()->inputs().end();
- for (input = m_pLinker->config()->inputs().begin(); input != inEnd; ++input) {
+ Module::input_iterator input, inEnd = m_pLinker->module()->input_end();
+ for (input = m_pLinker->module()->input_begin(); input != inEnd; ++input) {
dumpInput(**input, file, 1);
}
- dumpOutput(m_pLinker->config()->output(), file, 1);
+ dumpOutput(*m_pLinker->module(), file, 1);
// dump status
- ASSERT_TRUE(m_pLinker->getDriver()->mergeSections());
+ ASSERT_TRUE(m_pLinker->getObjLinker()->mergeSections());
}
diff --git a/unittests/ReadStageTest.h b/unittests/ReadStageTest.h
index 5fd4595..e799664 100644
--- a/unittests/ReadStageTest.h
+++ b/unittests/ReadStageTest.h
@@ -32,7 +32,7 @@
void dumpInput(const mcld::Input &pInput, mcld::FileHandle &pFile, size_t pIdent);
- void dumpOutput(const mcld::Output &pOutput, mcld::FileHandle &pFile, size_t pIdent);
+ void dumpOutput(const mcld::Module &pModule, mcld::FileHandle &pFile, size_t pIdent);
protected:
TestLinker* m_pLinker;
};
diff --git a/unittests/SectionDataTest.cpp b/unittests/SectionDataTest.cpp
index d100f56..5113068 100644
--- a/unittests/SectionDataTest.cpp
+++ b/unittests/SectionDataTest.cpp
@@ -41,29 +41,27 @@
//===----------------------------------------------------------------------===//
TEST_F( SectionDataTest, constructor_and_trivial_func ) {
- LDSection test("test", LDFileFormat::Null, 0, 0);
+ LDSection* test = LDSection::Create("test", LDFileFormat::Null, 0, 0);
- SectionData* s = new SectionData(test);
+ SectionData* s = SectionData::Create(*test);
EXPECT_TRUE(s->getSection().name() == "test" && \
s->getSection().kind() == LDFileFormat::Null);
- s->setAlignment(5566);
- EXPECT_TRUE(5566 == s->getAlignment());
- delete s;
+ LDSection::Destroy(test);
}
TEST_F( SectionDataTest, Fragment_list_and_iterator ) {
- LDSection test("test", LDFileFormat::Null, 0, 0);
- SectionData* s = new SectionData(test);
+ LDSection* test = LDSection::Create("test", LDFileFormat::Null, 0, 0);
+ SectionData* s = SectionData::Create(*test);
EXPECT_TRUE(s->empty());
- Fragment* f1 = new Fragment(Fragment::Alignment, s);
- Fragment* f2 = new Fragment(Fragment::Alignment, s);
- Fragment* f3 = new Fragment(Fragment::Region, s);
- Fragment* f4 = new Fragment(Fragment::Fillment, s);
- Fragment* f5 = new Fragment(Fragment::Relocation, s);
- Fragment* f6 = new Fragment(Fragment::Target, s);
+ new Fragment(Fragment::Alignment, s);
+ new Fragment(Fragment::Alignment, s);
+ new Fragment(Fragment::Region, s);
+ new Fragment(Fragment::Fillment, s);
+ new Fragment(Fragment::Relocation, s);
+ new Fragment(Fragment::Target, s);
EXPECT_TRUE(6 == s->size());
//iterator
@@ -82,5 +80,5 @@
++iter;
EXPECT_TRUE(iter == s->end());
- delete s;
+ LDSection::Destroy(test);
}
diff --git a/unittests/StaticResolverTest.cpp b/unittests/StaticResolverTest.cpp
index 439f21a..cb4c668 100644
--- a/unittests/StaticResolverTest.cpp
+++ b/unittests/StaticResolverTest.cpp
@@ -6,24 +6,14 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+#include "StaticResolverTest.h"
#include <mcld/Support/TargetSelect.h>
#include <mcld/LD/StaticResolver.h>
#include <mcld/LD/ResolveInfo.h>
-#include <mcld/LD/ResolveInfoFactory.h>
-#include <mcld/LD/DiagnosticPrinter.h>
-#include <mcld/LD/DiagnosticLineInfo.h>
-#include <mcld/LD/TextDiagnosticPrinter.h>
-#include <mcld/Support/MsgHandling.h>
-#include <mcld/MC/MCLDInfo.h>
-#include "StaticResolverTest.h"
+#include <mcld/LinkerConfig.h>
-#include <iostream>
-#include <mcld/Support/MsgHandling.h>
#include <mcld/Support/FileSystem.h>
-#include <mcld/LD/DiagnosticLineInfo.h>
-#include <mcld/LD/TextDiagnosticPrinter.h>
-using namespace std;
using namespace mcld;
using namespace mcldtest;
@@ -32,25 +22,20 @@
//===----------------------------------------------------------------------===//
// Constructor can do set-up work for all test here.
StaticResolverTest::StaticResolverTest()
- : m_pResolver(NULL), m_pFactory(NULL), m_pLDInfo(NULL), m_pLineInfo(NULL) {
+ : m_pResolver(NULL), m_pConfig(NULL) {
// create testee. modify it if need
m_pResolver = new StaticResolver();
- m_pFactory = new ResolveInfoFactory();
mcld::InitializeAllDiagnostics();
- m_pLDInfo = new MCLDInfo("arm-none-linux-gnueabi", 10, 10);
- m_pLineInfo = new DiagnosticLineInfo();
- mcld::InitializeDiagnosticEngine(*m_pLDInfo, m_pLineInfo, NULL);
+ m_pConfig = new LinkerConfig("arm-none-linux-gnueabi");
}
// Destructor can do clean-up work that doesn't throw exceptions here.
StaticResolverTest::~StaticResolverTest()
{
delete m_pResolver;
- delete m_pFactory;
- delete m_pLDInfo;
- delete m_pLineInfo;
+ delete m_pConfig;
}
// SetUp() will be called immediately before each test.
@@ -67,12 +52,12 @@
// Testcases
//
TEST_F( StaticResolverTest, MDEF ) {
- ResolveInfo* old_sym = m_pFactory->produce("abc");
- ResolveInfo* new_sym = m_pFactory->produce("abc");
+ ResolveInfo* old_sym = ResolveInfo::Create("abc");
+ ResolveInfo* new_sym = ResolveInfo::Create("abc");
new_sym->setDesc(ResolveInfo::Define);
old_sym->setDesc(ResolveInfo::Define);
- ASSERT_EQ( mcld::ResolveInfo::Define, new_sym->desc());
- ASSERT_EQ( mcld::ResolveInfo::Define, old_sym->desc());
+ ASSERT_TRUE( mcld::ResolveInfo::Define == new_sym->desc());
+ ASSERT_TRUE( mcld::ResolveInfo::Define == old_sym->desc());
ASSERT_TRUE( mcld::ResolveInfo::define_flag == new_sym->info());
ASSERT_TRUE( mcld::ResolveInfo::define_flag == old_sym->info());
bool override = true;
@@ -82,8 +67,8 @@
}
TEST_F( StaticResolverTest, DynDefAfterDynUndef ) {
- ResolveInfo* old_sym = m_pFactory->produce("abc");
- ResolveInfo* new_sym = m_pFactory->produce("abc");
+ ResolveInfo* old_sym = ResolveInfo::Create("abc");
+ ResolveInfo* new_sym = ResolveInfo::Create("abc");
new_sym->setBinding(ResolveInfo::Global);
old_sym->setBinding(ResolveInfo::Global);
@@ -96,21 +81,21 @@
old_sym->setSize(1);
- ASSERT_EQ( mcld::ResolveInfo::Global, new_sym->binding());
- ASSERT_EQ( mcld::ResolveInfo::Global, old_sym->binding());
- ASSERT_EQ( mcld::ResolveInfo::Undefined, new_sym->desc());
- ASSERT_EQ( mcld::ResolveInfo::Define, old_sym->desc());
+ ASSERT_TRUE( mcld::ResolveInfo::Global == new_sym->binding());
+ ASSERT_TRUE( mcld::ResolveInfo::Global == old_sym->binding());
+ ASSERT_TRUE( mcld::ResolveInfo::Undefined == new_sym->desc());
+ ASSERT_TRUE( mcld::ResolveInfo::Define == old_sym->desc());
bool override = false;
bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
ASSERT_TRUE(result);
ASSERT_FALSE( override );
- ASSERT_EQ(1, old_sym->size());
+ ASSERT_TRUE(1 == old_sym->size());
}
TEST_F( StaticResolverTest, DynDefAfterDynDef ) {
- ResolveInfo* old_sym = m_pFactory->produce("abc");
- ResolveInfo* new_sym = m_pFactory->produce("abc");
+ ResolveInfo* old_sym = ResolveInfo::Create("abc");
+ ResolveInfo* new_sym = ResolveInfo::Create("abc");
new_sym->setBinding(ResolveInfo::Global);
old_sym->setBinding(ResolveInfo::Global);
@@ -123,21 +108,21 @@
old_sym->setSize(1);
- ASSERT_EQ( mcld::ResolveInfo::Global, new_sym->binding());
- ASSERT_EQ( mcld::ResolveInfo::Global, old_sym->binding());
- ASSERT_EQ( mcld::ResolveInfo::Define, new_sym->desc());
- ASSERT_EQ( mcld::ResolveInfo::Define, old_sym->desc());
+ ASSERT_TRUE( mcld::ResolveInfo::Global == new_sym->binding());
+ ASSERT_TRUE( mcld::ResolveInfo::Global == old_sym->binding());
+ ASSERT_TRUE( mcld::ResolveInfo::Define == new_sym->desc());
+ ASSERT_TRUE( mcld::ResolveInfo::Define == old_sym->desc());
bool override = false;
bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
ASSERT_TRUE(result);
ASSERT_FALSE( override );
- ASSERT_EQ(1, old_sym->size());
+ ASSERT_TRUE(1 == old_sym->size());
}
TEST_F( StaticResolverTest, DynUndefAfterDynUndef ) {
- ResolveInfo* old_sym = m_pFactory->produce("abc");
- ResolveInfo* new_sym = m_pFactory->produce("abc");
+ ResolveInfo* old_sym = ResolveInfo::Create("abc");
+ ResolveInfo* new_sym = ResolveInfo::Create("abc");
new_sym->setBinding(ResolveInfo::Global);
old_sym->setBinding(ResolveInfo::Global);
@@ -150,30 +135,30 @@
old_sym->setSize(1);
- ASSERT_EQ( mcld::ResolveInfo::Global, new_sym->binding());
- ASSERT_EQ( mcld::ResolveInfo::Global, old_sym->binding());
- ASSERT_EQ( mcld::ResolveInfo::Undefined, new_sym->desc());
- ASSERT_EQ( mcld::ResolveInfo::Undefined, old_sym->desc());
+ ASSERT_TRUE( mcld::ResolveInfo::Global == new_sym->binding());
+ ASSERT_TRUE( mcld::ResolveInfo::Global == old_sym->binding());
+ ASSERT_TRUE( mcld::ResolveInfo::Undefined == new_sym->desc());
+ ASSERT_TRUE( mcld::ResolveInfo::Undefined == old_sym->desc());
bool override = false;
bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
ASSERT_TRUE(result);
ASSERT_FALSE( override );
- ASSERT_EQ(1, old_sym->size());
+ ASSERT_TRUE(1 == old_sym->size());
}
TEST_F( StaticResolverTest, OverrideWeakByGlobal )
{
- ResolveInfo* old_sym = m_pFactory->produce("abc");
- ResolveInfo* new_sym = m_pFactory->produce("abc");
+ ResolveInfo* old_sym = ResolveInfo::Create("abc");
+ ResolveInfo* new_sym = ResolveInfo::Create("abc");
new_sym->setBinding(ResolveInfo::Global);
old_sym->setBinding(ResolveInfo::Weak);
new_sym->setSize(0);
old_sym->setSize(1);
- ASSERT_EQ( mcld::ResolveInfo::Global, new_sym->binding());
- ASSERT_EQ( mcld::ResolveInfo::Weak, old_sym->binding());
+ ASSERT_TRUE( mcld::ResolveInfo::Global == new_sym->binding());
+ ASSERT_TRUE( mcld::ResolveInfo::Weak == old_sym->binding());
ASSERT_TRUE( mcld::ResolveInfo::global_flag == new_sym->info());
ASSERT_TRUE( mcld::ResolveInfo::weak_flag == old_sym->info());
@@ -181,12 +166,12 @@
bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
ASSERT_TRUE(result);
ASSERT_TRUE( override );
- ASSERT_EQ(0, old_sym->size());
+ ASSERT_TRUE(0 == old_sym->size());
}
TEST_F( StaticResolverTest, DynWeakAfterDynDef ) {
- ResolveInfo* old_sym = m_pFactory->produce("abc");
- ResolveInfo* new_sym = m_pFactory->produce("abc");
+ ResolveInfo* old_sym = ResolveInfo::Create("abc");
+ ResolveInfo* new_sym = ResolveInfo::Create("abc");
old_sym->setBinding(ResolveInfo::Weak);
new_sym->setBinding(ResolveInfo::Global);
@@ -201,30 +186,30 @@
old_sym->setSize(1);
- ASSERT_EQ( mcld::ResolveInfo::Weak, old_sym->binding());
- ASSERT_EQ( mcld::ResolveInfo::Global, new_sym->binding());
- ASSERT_EQ( mcld::ResolveInfo::Define, old_sym->desc());
- ASSERT_EQ( mcld::ResolveInfo::Define, new_sym->desc());
+ ASSERT_TRUE( mcld::ResolveInfo::Weak == old_sym->binding());
+ ASSERT_TRUE( mcld::ResolveInfo::Global == new_sym->binding());
+ ASSERT_TRUE( mcld::ResolveInfo::Define == old_sym->desc());
+ ASSERT_TRUE( mcld::ResolveInfo::Define == new_sym->desc());
bool override = false;
bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
ASSERT_TRUE(result);
ASSERT_FALSE( override );
- ASSERT_EQ(1, old_sym->size());
+ ASSERT_TRUE(1 == old_sym->size());
}
TEST_F( StaticResolverTest, MarkByBiggerCommon )
{
- ResolveInfo* old_sym = m_pFactory->produce("abc");
- ResolveInfo* new_sym = m_pFactory->produce("abc");
+ ResolveInfo* old_sym = ResolveInfo::Create("abc");
+ ResolveInfo* new_sym = ResolveInfo::Create("abc");
new_sym->setDesc(ResolveInfo::Common);
old_sym->setDesc(ResolveInfo::Common);
new_sym->setSize(999);
old_sym->setSize(0);
- ASSERT_EQ( mcld::ResolveInfo::Common, new_sym->desc());
- ASSERT_EQ( mcld::ResolveInfo::Common, old_sym->desc());
+ ASSERT_TRUE( mcld::ResolveInfo::Common == new_sym->desc());
+ ASSERT_TRUE( mcld::ResolveInfo::Common == old_sym->desc());
ASSERT_TRUE( mcld::ResolveInfo::common_flag == new_sym->info());
ASSERT_TRUE( mcld::ResolveInfo::common_flag == old_sym->info());
@@ -232,13 +217,13 @@
bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
ASSERT_TRUE(result);
ASSERT_FALSE( override );
- ASSERT_EQ(999, old_sym->size());
+ ASSERT_TRUE(999 == old_sym->size());
}
TEST_F( StaticResolverTest, OverrideByBiggerCommon )
{
- ResolveInfo* old_sym = m_pFactory->produce("abc");
- ResolveInfo* new_sym = m_pFactory->produce("abc");
+ ResolveInfo* old_sym = ResolveInfo::Create("abc");
+ ResolveInfo* new_sym = ResolveInfo::Create("abc");
new_sym->setDesc(ResolveInfo::Common);
old_sym->setDesc(ResolveInfo::Common);
@@ -246,9 +231,9 @@
new_sym->setSize(999);
old_sym->setSize(0);
- ASSERT_EQ( ResolveInfo::Common, new_sym->desc());
- ASSERT_EQ( ResolveInfo::Common, old_sym->desc());
- ASSERT_EQ( ResolveInfo::Weak, old_sym->binding());
+ ASSERT_TRUE( ResolveInfo::Common == new_sym->desc());
+ ASSERT_TRUE( ResolveInfo::Common == old_sym->desc());
+ ASSERT_TRUE( ResolveInfo::Weak == old_sym->binding());
ASSERT_TRUE( ResolveInfo::common_flag == new_sym->info());
ASSERT_TRUE( (ResolveInfo::weak_flag | ResolveInfo::common_flag) == old_sym->info());
@@ -257,13 +242,13 @@
bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
ASSERT_TRUE(result);
ASSERT_TRUE( override );
- ASSERT_EQ(999, old_sym->size());
+ ASSERT_TRUE(999 == old_sym->size());
}
TEST_F( StaticResolverTest, OverrideCommonByDefine)
{
- ResolveInfo* old_sym = m_pFactory->produce("abc");
- ResolveInfo* new_sym = m_pFactory->produce("abc");
+ ResolveInfo* old_sym = ResolveInfo::Create("abc");
+ ResolveInfo* new_sym = ResolveInfo::Create("abc");
old_sym->setDesc(ResolveInfo::Common);
old_sym->setSize(0);
@@ -271,8 +256,8 @@
new_sym->setDesc(ResolveInfo::Define);
new_sym->setSize(999);
- ASSERT_EQ( ResolveInfo::Define, new_sym->desc());
- ASSERT_EQ( ResolveInfo::Common, old_sym->desc());
+ ASSERT_TRUE( ResolveInfo::Define == new_sym->desc());
+ ASSERT_TRUE( ResolveInfo::Common == old_sym->desc());
ASSERT_TRUE( ResolveInfo::define_flag == new_sym->info());
ASSERT_TRUE( ResolveInfo::common_flag == old_sym->info());
@@ -281,12 +266,12 @@
bool result = m_pResolver->resolve(*old_sym, *new_sym, override);
ASSERT_TRUE(result);
ASSERT_TRUE( override );
- ASSERT_EQ(999, old_sym->size());
+ ASSERT_TRUE(999 == old_sym->size());
}
TEST_F( StaticResolverTest, SetUpDesc)
{
- ResolveInfo* sym = m_pFactory->produce("abc");
+ ResolveInfo* sym = ResolveInfo::Create("abc");
sym->setIsSymbol(true);
@@ -300,10 +285,10 @@
ASSERT_FALSE( sym->isDyn() );
ASSERT_FALSE( sym->isCommon() );
ASSERT_FALSE( sym->isIndirect() );
- ASSERT_EQ( ResolveInfo::NoType, sym->type());
- ASSERT_EQ( 0, sym->desc() );
- ASSERT_EQ( 0, sym->binding() );
- ASSERT_EQ( 0, sym->other() );
+ ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+ ASSERT_TRUE( 0 == sym->desc() );
+ ASSERT_TRUE( 0 == sym->binding() );
+ ASSERT_TRUE( 0 == sym->other() );
sym->setIsSymbol(false);
ASSERT_FALSE( sym->isSymbol() );
@@ -316,10 +301,10 @@
ASSERT_FALSE( sym->isDyn() );
ASSERT_FALSE( sym->isCommon() );
ASSERT_FALSE( sym->isIndirect() );
- ASSERT_EQ( ResolveInfo::NoType, sym->type());
- ASSERT_EQ( 0, sym->desc() );
- ASSERT_EQ( 0, sym->binding() );
- ASSERT_EQ( 0, sym->other() );
+ ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+ ASSERT_TRUE( 0 == sym->desc() );
+ ASSERT_TRUE( 0 == sym->binding() );
+ ASSERT_TRUE( 0 == sym->other() );
sym->setDesc(ResolveInfo::Define);
ASSERT_FALSE( sym->isSymbol() );
@@ -332,10 +317,10 @@
ASSERT_FALSE( sym->isDyn() );
ASSERT_FALSE( sym->isCommon() );
ASSERT_FALSE( sym->isIndirect() );
- ASSERT_EQ( ResolveInfo::NoType, sym->type());
- ASSERT_EQ( ResolveInfo::Define, sym->desc() );
- ASSERT_EQ( 0, sym->binding() );
- ASSERT_EQ( 0, sym->other() );
+ ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+ ASSERT_TRUE( ResolveInfo::Define == sym->desc() );
+ ASSERT_TRUE( 0 == sym->binding() );
+ ASSERT_TRUE( 0 == sym->other() );
sym->setDesc(ResolveInfo::Common);
ASSERT_FALSE( sym->isSymbol() );
@@ -348,10 +333,10 @@
ASSERT_FALSE( sym->isUndef() );
ASSERT_TRUE( sym->isCommon() );
ASSERT_FALSE( sym->isIndirect() );
- ASSERT_EQ( ResolveInfo::NoType, sym->type());
- ASSERT_EQ( ResolveInfo::Common, sym->desc() );
- ASSERT_EQ( 0, sym->binding() );
- ASSERT_EQ( 0, sym->other() );
+ ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+ ASSERT_TRUE( ResolveInfo::Common == sym->desc() );
+ ASSERT_TRUE( 0 == sym->binding() );
+ ASSERT_TRUE( 0 == sym->other() );
sym->setDesc(ResolveInfo::Indirect);
ASSERT_FALSE( sym->isSymbol() );
@@ -363,10 +348,10 @@
ASSERT_FALSE( sym->isUndef() );
ASSERT_FALSE( sym->isCommon() );
ASSERT_TRUE( sym->isIndirect() );
- ASSERT_EQ( ResolveInfo::NoType, sym->type());
- ASSERT_EQ( ResolveInfo::Indirect, sym->desc() );
- ASSERT_EQ( 0, sym->binding() );
- ASSERT_EQ( 0, sym->other() );
+ ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+ ASSERT_TRUE( ResolveInfo::Indirect == sym->desc() );
+ ASSERT_TRUE( 0 == sym->binding() );
+ ASSERT_TRUE( 0 == sym->other() );
sym->setDesc(ResolveInfo::Undefined);
ASSERT_FALSE( sym->isSymbol() );
@@ -378,15 +363,15 @@
ASSERT_FALSE( sym->isDefine() );
ASSERT_FALSE( sym->isCommon() );
ASSERT_FALSE( sym->isIndirect() );
- ASSERT_EQ( ResolveInfo::NoType, sym->type());
- ASSERT_EQ( 0, sym->desc() );
- ASSERT_EQ( 0, sym->binding() );
- ASSERT_EQ( 0, sym->other() );
+ ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+ ASSERT_TRUE( 0 == sym->desc() );
+ ASSERT_TRUE( 0 == sym->binding() );
+ ASSERT_TRUE( 0 == sym->other() );
}
TEST_F( StaticResolverTest, SetUpBinding)
{
- ResolveInfo* sym = m_pFactory->produce("abc");
+ ResolveInfo* sym = ResolveInfo::Create("abc");
sym->setIsSymbol(true);
@@ -400,10 +385,10 @@
ASSERT_FALSE( sym->isDyn() );
ASSERT_FALSE( sym->isCommon() );
ASSERT_FALSE( sym->isIndirect() );
- ASSERT_EQ( ResolveInfo::NoType, sym->type());
- ASSERT_EQ( 0, sym->desc() );
- ASSERT_EQ( 0, sym->binding() );
- ASSERT_EQ( 0, sym->other() );
+ ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+ ASSERT_TRUE( 0 == sym->desc() );
+ ASSERT_TRUE( 0 == sym->binding() );
+ ASSERT_TRUE( 0 == sym->other() );
sym->setBinding(ResolveInfo::Global);
ASSERT_TRUE( sym->isSymbol() );
@@ -415,10 +400,10 @@
ASSERT_FALSE( sym->isDyn() );
ASSERT_FALSE( sym->isCommon() );
ASSERT_FALSE( sym->isIndirect() );
- ASSERT_EQ( ResolveInfo::NoType, sym->type());
- ASSERT_EQ( 0, sym->desc() );
- ASSERT_EQ( ResolveInfo::Global, sym->binding() );
- ASSERT_EQ( 0, sym->other() );
+ ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+ ASSERT_TRUE( 0 == sym->desc() );
+ ASSERT_TRUE( ResolveInfo::Global == sym->binding() );
+ ASSERT_TRUE( 0 == sym->other() );
sym->setBinding(ResolveInfo::Weak);
ASSERT_TRUE( sym->isSymbol() );
@@ -430,10 +415,10 @@
ASSERT_TRUE( sym->isUndef() );
ASSERT_FALSE( sym->isCommon() );
ASSERT_FALSE( sym->isIndirect() );
- ASSERT_EQ( ResolveInfo::NoType, sym->type());
- ASSERT_EQ( 0, sym->desc() );
- ASSERT_EQ( ResolveInfo::Weak, sym->binding() );
- ASSERT_EQ( 0, sym->other() );
+ ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+ ASSERT_TRUE( 0 == sym->desc() );
+ ASSERT_TRUE( ResolveInfo::Weak == sym->binding() );
+ ASSERT_TRUE( 0 == sym->other() );
sym->setBinding(ResolveInfo::Local);
ASSERT_TRUE( sym->isSymbol() );
@@ -445,9 +430,9 @@
ASSERT_TRUE( sym->isUndef() );
ASSERT_FALSE( sym->isCommon() );
ASSERT_FALSE( sym->isIndirect() );
- ASSERT_EQ( ResolveInfo::NoType, sym->type());
- ASSERT_EQ( 0, sym->desc() );
- ASSERT_EQ( ResolveInfo::Local, sym->binding() );
- ASSERT_EQ( 0, sym->other() );
+ ASSERT_TRUE( ResolveInfo::NoType == sym->type());
+ ASSERT_TRUE( 0 == sym->desc() );
+ ASSERT_TRUE( ResolveInfo::Local == sym->binding() );
+ ASSERT_TRUE( 0 == sym->other() );
}
diff --git a/unittests/StaticResolverTest.h b/unittests/StaticResolverTest.h
index e4ffa50..89157f0 100644
--- a/unittests/StaticResolverTest.h
+++ b/unittests/StaticResolverTest.h
@@ -10,12 +10,13 @@
#define STATICRESOLVER_TEST_H
#include <gtest.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
-namespace mcld
-{
+namespace mcld {
+
class StaticResolver;
class ResolveInfoFactory;
+class DiagnosticPrinter;
} // namespace for mcld
@@ -44,9 +45,7 @@
protected:
mcld::StaticResolver* m_pResolver;
- mcld::ResolveInfoFactory* m_pFactory;
- mcld::MCLDInfo* m_pLDInfo;
- mcld::DiagnosticLineInfo* m_pLineInfo;
+ mcld::LinkerConfig* m_pConfig;
mcld::DiagnosticPrinter* m_pPrinter;
};
diff --git a/unittests/SymbolCategoryTest.cpp b/unittests/SymbolCategoryTest.cpp
index 4233c3e..07f479b 100644
--- a/unittests/SymbolCategoryTest.cpp
+++ b/unittests/SymbolCategoryTest.cpp
@@ -20,14 +20,14 @@
// Constructor can do set-up work for all test here.
SymbolCategoryTest::SymbolCategoryTest()
{
- // create testee. modify it if need
- m_pTestee = new SymbolCategory();
+ // create testee. modify it if need
+ m_pTestee = new SymbolCategory();
}
// Destructor can do clean-up work that doesn't throw exceptions here.
SymbolCategoryTest::~SymbolCategoryTest()
{
- delete m_pTestee;
+ delete m_pTestee;
}
// SetUp() will be called immediately before each test.
@@ -45,35 +45,29 @@
//
TEST_F(SymbolCategoryTest, upward_test) {
- ResolveInfo* a = m_InfoFactory.produce("a");
- ResolveInfo* b = m_InfoFactory.produce("b");
- ResolveInfo* c = m_InfoFactory.produce("c");
- ResolveInfo* d = m_InfoFactory.produce("d");
- ResolveInfo* e = m_InfoFactory.produce("e");
+ ResolveInfo* a = ResolveInfo::Create("a");
+ ResolveInfo* b = ResolveInfo::Create("b");
+ ResolveInfo* c = ResolveInfo::Create("c");
+ ResolveInfo* d = ResolveInfo::Create("d");
+ ResolveInfo* e = ResolveInfo::Create("e");
e->setBinding(ResolveInfo::Global);
d->setBinding(ResolveInfo::Weak);
c->setDesc(ResolveInfo::Common);
c->setBinding(ResolveInfo::Global);
b->setBinding(ResolveInfo::Local);
a->setType(ResolveInfo::File);
-
- LDSymbol aa;
- LDSymbol bb;
- LDSymbol cc;
- LDSymbol dd;
- LDSymbol ee;
- aa.setResolveInfo(*a);
- bb.setResolveInfo(*b);
- cc.setResolveInfo(*c);
- dd.setResolveInfo(*d);
- ee.setResolveInfo(*e);
+ LDSymbol* aa = LDSymbol::Create(*a);
+ LDSymbol* bb = LDSymbol::Create(*b);
+ LDSymbol* cc = LDSymbol::Create(*c);
+ LDSymbol* dd = LDSymbol::Create(*d);
+ LDSymbol* ee = LDSymbol::Create(*e);
- m_pTestee->add(ee);
- m_pTestee->add(dd);
- m_pTestee->add(cc);
- m_pTestee->add(bb);
- m_pTestee->add(aa);
+ m_pTestee->add(*ee);
+ m_pTestee->add(*dd);
+ m_pTestee->add(*cc);
+ m_pTestee->add(*bb);
+ m_pTestee->add(*aa);
SymbolCategory::iterator sym = m_pTestee->begin();
ASSERT_STREQ("a", (*sym)->name());
@@ -86,9 +80,65 @@
++sym;
ASSERT_STREQ("e", (*sym)->name());
- ASSERT_EQ(2, m_pTestee->numOfLocals());
- ASSERT_EQ(1, m_pTestee->numOfCommons());
- ASSERT_EQ(2, m_pTestee->numOfRegulars());
- ASSERT_EQ(5, m_pTestee->numOfSymbols());
+ ASSERT_TRUE(2 == m_pTestee->numOfLocals());
+ ASSERT_TRUE(1 == m_pTestee->numOfCommons());
+ ASSERT_TRUE(2 == m_pTestee->numOfRegulars());
+ ASSERT_TRUE(5 == m_pTestee->numOfSymbols());
}
+TEST_F(SymbolCategoryTest, change_local_to_tls) {
+ ResolveInfo* a = ResolveInfo::Create("a");
+ ResolveInfo* b = ResolveInfo::Create("b");
+ ResolveInfo* c = ResolveInfo::Create("c");
+ ResolveInfo* d = ResolveInfo::Create("d");
+ ResolveInfo* e = ResolveInfo::Create("e");
+
+ a->setBinding(ResolveInfo::Local);
+ b->setBinding(ResolveInfo::Local);
+ c->setBinding(ResolveInfo::Local);
+ d->setDesc(ResolveInfo::Common);
+ d->setBinding(ResolveInfo::Global);
+ e->setBinding(ResolveInfo::Global);
+
+ LDSymbol* aa = LDSymbol::Create(*a);
+ LDSymbol* bb = LDSymbol::Create(*b);
+ LDSymbol* cc = LDSymbol::Create(*c);
+ LDSymbol* dd = LDSymbol::Create(*d);
+ LDSymbol* ee = LDSymbol::Create(*e);
+
+ a->setSymPtr(aa);
+ b->setSymPtr(bb);
+ c->setSymPtr(cc);
+ d->setSymPtr(dd);
+ e->setSymPtr(ee);
+
+ m_pTestee->add(*ee);
+ m_pTestee->add(*dd);
+ m_pTestee->add(*cc);
+ m_pTestee->add(*bb);
+ m_pTestee->add(*aa);
+
+ SymbolCategory::iterator sym = m_pTestee->begin();
+ ASSERT_STREQ("c", (*sym)->name());
+ ++sym;
+ ASSERT_STREQ("b", (*sym)->name());
+ ++sym;
+ ASSERT_STREQ("a", (*sym)->name());
+ ++sym;
+ ASSERT_STREQ("d", (*sym)->name());
+ ++sym;
+ ASSERT_STREQ("e", (*sym)->name());
+
+ m_pTestee->changeLocalToTLS(*bb);
+
+ sym = m_pTestee->begin();
+ ASSERT_STREQ("c", (*sym)->name());
+ ++sym;
+ ASSERT_STREQ("a", (*sym)->name());
+ ++sym;
+ ASSERT_STREQ("b", (*sym)->name());
+ ++sym;
+ ASSERT_STREQ("d", (*sym)->name());
+ ++sym;
+ ASSERT_STREQ("e", (*sym)->name());
+}
diff --git a/unittests/SymbolCategoryTest.h b/unittests/SymbolCategoryTest.h
index f721368..ff5f1a6 100644
--- a/unittests/SymbolCategoryTest.h
+++ b/unittests/SymbolCategoryTest.h
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#ifndef MCLD_SYMBOLCATEGORY_TEST_H
#define MCLD_SYMBOLCATEGORY_TEST_H
-#include <mcld/LD/ResolveInfoFactory.h>
#include <gtest.h>
@@ -43,7 +42,6 @@
protected:
mcld::SymbolCategory* m_pTestee;
- mcld::ResolveInfoFactory m_InfoFactory;
};
} // namespace of mcldtest
diff --git a/unittests/TestLinkerTest.cpp b/unittests/TestLinkerTest.cpp
index 272cd89..0b1a141 100644
--- a/unittests/TestLinkerTest.cpp
+++ b/unittests/TestLinkerTest.cpp
@@ -11,6 +11,7 @@
#include <mcld/Support/Path.h>
#include <mcld/MC/MCLDDirectory.h>
+#include <mcld/MC/InputFactory.h>
using namespace mcld;
using namespace mcld::test;
@@ -35,13 +36,13 @@
m_pLinker->initialize("arm-none-linux-gnueabi");
// set up target-dependent constraints of attributes
- m_pLinker->config()->attrFactory().constraint().enableWholeArchive();
- m_pLinker->config()->attrFactory().constraint().disableAsNeeded();
- m_pLinker->config()->attrFactory().constraint().setSharedSystem();
+ m_pLinker->config()->attribute().constraint().enableWholeArchive();
+ m_pLinker->config()->attribute().constraint().disableAsNeeded();
+ m_pLinker->config()->attribute().constraint().setSharedSystem();
// set up the predefined attributes
- m_pLinker->config()->attrFactory().predefined().setWholeArchive();
- m_pLinker->config()->attrFactory().predefined().setDynamic();
+ m_pLinker->config()->attribute().predefined().setWholeArchive();
+ m_pLinker->config()->attribute().predefined().setDynamic();
// set up target dependent options
mcld::sys::fs::Path path = TOPDIR;
diff --git a/unittests/UniqueGCFactoryBaseTest.cpp b/unittests/UniqueGCFactoryBaseTest.cpp
index 32447c2..f8e098a 100644
--- a/unittests/UniqueGCFactoryBaseTest.cpp
+++ b/unittests/UniqueGCFactoryBaseTest.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include <mcld/MC/ContextFactory.h>
#include <mcld/Support/MemoryAreaFactory.h>
-#include <mcld/Support/MsgHandling.h>
#include <mcld/Support/TargetSelect.h>
#include <mcld/Support/Path.h>
#include "UniqueGCFactoryBaseTest.h"
@@ -22,16 +21,13 @@
{
InitializeAllDiagnostics();
- m_pLDInfo = new MCLDInfo("arm-none-linux-gnueabi", 10, 10);
- m_pLineInfo = new DiagnosticLineInfo();
- mcld::InitializeDiagnosticEngine(*m_pLDInfo, m_pLineInfo, NULL);
+ m_pConfig = new LinkerConfig("arm-none-linux-gnueabi");
}
// Destructor can do clean-up work that doesn't throw exceptions here.
UniqueGCFactoryBaseTest::~UniqueGCFactoryBaseTest()
{
- delete m_pLDInfo;
- delete m_pLineInfo;
+ delete m_pConfig;
}
// SetUp() will be called immediately before each test.
@@ -51,7 +47,7 @@
ContextFactory *contextFactory = new ContextFactory(10);
contextFactory->produce("/");
contextFactory->produce("ab/c");
- ASSERT_EQ( 2, contextFactory->size());
+ ASSERT_TRUE( 2 == contextFactory->size());
delete contextFactory;
}
@@ -59,7 +55,7 @@
ContextFactory *contextFactory = new ContextFactory(10);
LDContext* context1 = contextFactory->produce("/");
contextFactory->produce("ab/c");
- ASSERT_EQ( 2, contextFactory->size());
+ ASSERT_TRUE( 2 == contextFactory->size());
LDContext* context2 = contextFactory->produce("/");
ASSERT_EQ( context1, context2 );
delete contextFactory;
@@ -69,7 +65,7 @@
ContextFactory *contextFactory = new ContextFactory(10);
LDContext* context1 = contextFactory->produce("abc/def");
contextFactory->produce("ab/c");
- ASSERT_EQ( 2, contextFactory->size());
+ ASSERT_TRUE( 2 == contextFactory->size());
LDContext* context2 = contextFactory->produce("ttt/../abc/def");
ASSERT_EQ( context1, context2 );
delete contextFactory;
@@ -90,7 +86,7 @@
ASSERT_EQ(area1, area3);
ASSERT_FALSE( memFactory->empty());
- ASSERT_EQ( 2, memFactory->size());
+ ASSERT_TRUE( 2 == memFactory->size());
MemoryAreaFactory::iterator aIter = memFactory->begin();
ASSERT_EQ( area1, &(*aIter));
++aIter;
diff --git a/unittests/UniqueGCFactoryBaseTest.h b/unittests/UniqueGCFactoryBaseTest.h
index 525c8c4..c2f1c1b 100644
--- a/unittests/UniqueGCFactoryBaseTest.h
+++ b/unittests/UniqueGCFactoryBaseTest.h
@@ -10,9 +10,8 @@
#define UNIQUE_GCFACTORYBASE_TEST_H
#include <mcld/Support/UniqueGCFactory.h>
-#include <mcld/MC/MCLDInfo.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/LD/DiagnosticPrinter.h>
-#include <mcld/LD/DiagnosticLineInfo.h>
#include <gtest.h>
namespace mcldtest
@@ -26,22 +25,20 @@
class UniqueGCFactoryBaseTest : public ::testing::Test
{
public:
- // Constructor can do set-up work for all test here.
- UniqueGCFactoryBaseTest();
+ // Constructor can do set-up work for all test here.
+ UniqueGCFactoryBaseTest();
- // Destructor can do clean-up work that doesn't throw exceptions here.
- virtual ~UniqueGCFactoryBaseTest();
+ // Destructor can do clean-up work that doesn't throw exceptions here.
+ virtual ~UniqueGCFactoryBaseTest();
- // SetUp() will be called immediately before each test.
- virtual void SetUp();
+ // SetUp() will be called immediately before each test.
+ virtual void SetUp();
- // TearDown() will be called immediately after each test.
- virtual void TearDown();
+ // TearDown() will be called immediately after each test.
+ virtual void TearDown();
private:
- mcld::MCLDInfo* m_pLDInfo;
- mcld::DiagnosticLineInfo* m_pLineInfo;
- mcld::DiagnosticPrinter* m_pPrinter;
+ mcld::LinkerConfig* m_pConfig;
};
} // namespace of mcldtest
diff --git a/unittests/read_stage.xml b/unittests/read_stage.xml
deleted file mode 100644
index cc061d6..0000000
--- a/unittests/read_stage.xml
+++ /dev/null
@@ -1,273 +0,0 @@
- <input name="/Users/lubatang/Project/MCLinker/build/../src-tree/test/libs/ARM/Android/android-14/crtbegin_so.o">
- <section name=""/>
- <section name=".text"/>
- <section name=".rel.text"/>
- <section name=".data"/>
- <section name=".bss"/>
- <section name=".init_array"/>
- <section name=".fini_array"/>
- <section name=".rel.fini_array"/>
- <section name=".ARM.attributes"/>
- <section name=".shstrtab"/>
- <section name=".symtab"/>
- <section name=".strtab"/>
- </input>
- <input name="/Users/lubatang/Project/MCLinker/build/../src-tree/test/Android/Plasma/ARM/plasma.o">
- <section name=""/>
- <section name=".text"/>
- <section name=".rel.text"/>
- <section name=".text.now_ms"/>
- <section name=".rel.text.now_ms"/>
- <section name=".text.init_angles"/>
- <section name=".rel.text.init_angles"/>
- <section name=".text.angle_sin"/>
- <section name=".rel.text.angle_sin"/>
- <section name=".text.fixed_sin"/>
- <section name=".rel.text.fixed_sin"/>
- <section name=".text.make565"/>
- <section name=".text.init_palette"/>
- <section name=".rel.text.init_palette"/>
- <section name=".text.palette_from_fixed"/>
- <section name=".rel.text.palette_from_fixed"/>
- <section name=".text.init_tables"/>
- <section name=".rel.text.init_tables"/>
- <section name=".text.fill_plasma"/>
- <section name=".rel.text.fill_plasma"/>
- <section name=".text.stats_init"/>
- <section name=".rel.text.stats_init"/>
- <section name=".text.stats_startFrame"/>
- <section name=".rel.text.stats_startFrame"/>
- <section name=".text.stats_endFrame"/>
- <section name=".rel.text.stats_endFrame"/>
- <section name=".text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
- <section name=".rel.text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
- <section name=".rodata"/>
- <section name=".ARM.extab.text.now_ms"/>
- <section name=".ARM.exidx.text.now_ms"/>
- <section name=".rel.ARM.exidx.text.now_ms"/>
- <section name=".ARM.extab.text.init_angles"/>
- <section name=".ARM.exidx.text.init_angles"/>
- <section name=".rel.ARM.exidx.text.init_angles"/>
- <section name=".ARM.extab.text.angle_sin"/>
- <section name=".ARM.exidx.text.angle_sin"/>
- <section name=".rel.ARM.exidx.text.angle_sin"/>
- <section name=".ARM.extab.text.fixed_sin"/>
- <section name=".ARM.exidx.text.fixed_sin"/>
- <section name=".rel.ARM.exidx.text.fixed_sin"/>
- <section name=".ARM.extab.text.make565"/>
- <section name=".ARM.exidx.text.make565"/>
- <section name=".rel.ARM.exidx.text.make565"/>
- <section name=".ARM.extab.text.init_palette"/>
- <section name=".ARM.exidx.text.init_palette"/>
- <section name=".rel.ARM.exidx.text.init_palette"/>
- <section name=".ARM.extab.text.palette_from_fixed"/>
- <section name=".ARM.exidx.text.palette_from_fixed"/>
- <section name=".rel.ARM.exidx.text.palette_from_fixed"/>
- <section name=".ARM.extab.text.init_tables"/>
- <section name=".ARM.exidx.text.init_tables"/>
- <section name=".rel.ARM.exidx.text.init_tables"/>
- <section name=".ARM.extab.text.fill_plasma"/>
- <section name=".ARM.exidx.text.fill_plasma"/>
- <section name=".rel.ARM.exidx.text.fill_plasma"/>
- <section name=".ARM.extab.text.stats_init"/>
- <section name=".ARM.exidx.text.stats_init"/>
- <section name=".rel.ARM.exidx.text.stats_init"/>
- <section name=".ARM.extab.text.stats_startFrame"/>
- <section name=".ARM.exidx.text.stats_startFrame"/>
- <section name=".rel.ARM.exidx.text.stats_startFrame"/>
- <section name=".ARM.extab.text.stats_endFrame"/>
- <section name=".ARM.exidx.text.stats_endFrame"/>
- <section name=".rel.ARM.exidx.text.stats_endFrame"/>
- <section name=".ARM.extab.text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
- <section name=".ARM.exidx.text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
- <section name=".rel.ARM.exidx.text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
- <section name=".ARM.extab"/>
- <section name=".ARM.exidx"/>
- <section name=".rel.ARM.exidx"/>
- <section name=".data"/>
- <section name=".bss"/>
- <section name=".comment"/>
- <section name=".debug_aranges"/>
- <section name=".rel.debug_aranges"/>
- <section name=".debug_pubnames"/>
- <section name=".rel.debug_pubnames"/>
- <section name=".debug_info"/>
- <section name=".rel.debug_info"/>
- <section name=".debug_abbrev"/>
- <section name=".debug_line"/>
- <section name=".rel.debug_line"/>
- <section name=".debug_frame"/>
- <section name=".rel.debug_frame"/>
- <section name=".debug_str"/>
- <section name=".debug_loc"/>
- <section name=".rel.debug_loc"/>
- <section name=".debug_ranges"/>
- <section name=".rel.debug_ranges"/>
- <section name=".note.GNU-stack"/>
- <section name=".ARM.attributes"/>
- <section name=".shstrtab"/>
- <section name=".symtab"/>
- <section name=".strtab"/>
- </input>
- <input name="libm.so">
- <section name=""/>
- <section name=".hash"/>
- <section name=".dynsym"/>
- <section name=".dynstr"/>
- <section name=".text"/>
- <section name=".dynamic"/>
- <section name=".got"/>
- <section name=".bss"/>
- <section name=".ARM.attributes"/>
- <section name=".comment"/>
- <section name=".shstrtab"/>
- <section name=".symtab"/>
- <section name=".strtab"/>
- </input>
- <input name="liblog.so">
- <section name=""/>
- <section name=".hash"/>
- <section name=".dynsym"/>
- <section name=".dynstr"/>
- <section name=".text"/>
- <section name=".dynamic"/>
- <section name=".got"/>
- <section name=".ARM.attributes"/>
- <section name=".comment"/>
- <section name=".shstrtab"/>
- <section name=".symtab"/>
- <section name=".strtab"/>
- </input>
- <input name="libjnigraphics.so">
- <section name=""/>
- <section name=".hash"/>
- <section name=".dynsym"/>
- <section name=".dynstr"/>
- <section name=".text"/>
- <section name=".dynamic"/>
- <section name=".got"/>
- <section name=".ARM.attributes"/>
- <section name=".comment"/>
- <section name=".shstrtab"/>
- <section name=".symtab"/>
- <section name=".strtab"/>
- </input>
- <input name="libc.so">
- <section name=""/>
- <section name=".hash"/>
- <section name=".dynsym"/>
- <section name=".dynstr"/>
- <section name=".text"/>
- <section name=".dynamic"/>
- <section name=".got"/>
- <section name=".bss"/>
- <section name=".ARM.attributes"/>
- <section name=".comment"/>
- <section name=".shstrtab"/>
- <section name=".symtab"/>
- <section name=".strtab"/>
- </input>
- <input name="/Users/lubatang/Project/MCLinker/build/../src-tree/test/libs/ARM/Android/android-14/crtend_so.o">
- <section name=""/>
- <section name=".text"/>
- <section name=".data"/>
- <section name=".bss"/>
- <section name=".init_array"/>
- <section name=".fini_array"/>
- <section name=".ARM.attributes"/>
- <section name=".shstrtab"/>
- <section name=".symtab"/>
- <section name=".strtab"/>
- </input>
- <output name="">
- <section name=".text"/>
- <section name=""/>
- <section name=".rodata"/>
- <section name=".bss"/>
- <section name=".comment"/>
- <section name=".data"/>
- <section name=".debug"/>
- <section name=".init"/>
- <section name=".init_array"/>
- <section name=".fini"/>
- <section name=".fini_array"/>
- <section name=".line"/>
- <section name=".preinit_array"/>
- <section name=".shstrtab"/>
- <section name=".symtab"/>
- <section name=".strtab"/>
- <section name=".tbss"/>
- <section name=".tdata"/>
- <section name=".ctor"/>
- <section name=".data.rel.ro"/>
- <section name=".dtors"/>
- <section name=".eh_frame"/>
- <section name=".gcc_except_table"/>
- <section name=".gnu.version"/>
- <section name=".gnu.version_d"/>
- <section name=".gnu.version_r"/>
- <section name=".jcr"/>
- <section name=".stab"/>
- <section name=".stabstr"/>
- <section name=".dynsym"/>
- <section name=".dynstr"/>
- <section name=".interp"/>
- <section name=".hash"/>
- <section name=".dynamic"/>
- <section name=".rela.dyn"/>
- <section name=".rela.plt"/>
- <section name=".rel.dyn"/>
- <section name=".rel.plt"/>
- <section name=".got"/>
- <section name=".plt"/>
- <section name=".got.plt"/>
- <section name=".eh_frame_hdr"/>
- <section name=".ARM.exidx"/>
- <section name=".ARM.extab"/>
- <section name=".ARM.attributes"/>
- <section name=".rel.text"/>
- <section name=".rel.fini_array"/>
- <section name=".rel.text.now_ms"/>
- <section name=".rel.text.init_angles"/>
- <section name=".rel.text.angle_sin"/>
- <section name=".rel.text.fixed_sin"/>
- <section name=".rel.text.init_palette"/>
- <section name=".rel.text.palette_from_fixed"/>
- <section name=".rel.text.init_tables"/>
- <section name=".rel.text.fill_plasma"/>
- <section name=".rel.text.stats_init"/>
- <section name=".rel.text.stats_startFrame"/>
- <section name=".rel.text.stats_endFrame"/>
- <section name=".rel.text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
- <section name=".rel.ARM.exidx.text.now_ms"/>
- <section name=".rel.ARM.exidx.text.init_angles"/>
- <section name=".rel.ARM.exidx.text.angle_sin"/>
- <section name=".rel.ARM.exidx.text.fixed_sin"/>
- <section name=".rel.ARM.exidx.text.make565"/>
- <section name=".rel.ARM.exidx.text.init_palette"/>
- <section name=".rel.ARM.exidx.text.palette_from_fixed"/>
- <section name=".rel.ARM.exidx.text.init_tables"/>
- <section name=".rel.ARM.exidx.text.fill_plasma"/>
- <section name=".rel.ARM.exidx.text.stats_init"/>
- <section name=".rel.ARM.exidx.text.stats_startFrame"/>
- <section name=".rel.ARM.exidx.text.stats_endFrame"/>
- <section name=".rel.ARM.exidx.text.Java_com_example_plasma_PlasmaView_renderPlasma"/>
- <section name=".rel.ARM.exidx"/>
- <section name=".debug_aranges"/>
- <section name=".rel.debug_aranges"/>
- <section name=".debug_pubnames"/>
- <section name=".rel.debug_pubnames"/>
- <section name=".debug_info"/>
- <section name=".rel.debug_info"/>
- <section name=".debug_abbrev"/>
- <section name=".debug_line"/>
- <section name=".rel.debug_line"/>
- <section name=".debug_frame"/>
- <section name=".rel.debug_frame"/>
- <section name=".debug_str"/>
- <section name=".debug_loc"/>
- <section name=".rel.debug_loc"/>
- <section name=".debug_ranges"/>
- <section name=".rel.debug_ranges"/>
- <section name=".note.GNU-stack"/>
- </output>
diff --git a/unittests/test2.txt b/unittests/test2.txt
index f1e9c6a..1672643 100644
--- a/unittests/test2.txt
+++ b/unittests/test2.txt
Binary files differ