Home | History | Annotate | Download | only in Mips
      1 //===- MipsGOT.h ----------------------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #ifndef TARGET_MIPS_MIPSGOT_H
     10 #define TARGET_MIPS_MIPSGOT_H
     11 #include <map>
     12 #include <vector>
     13 
     14 
     15 #include <mcld/ADT/SizeTraits.h>
     16 #include <mcld/Target/GOT.h>
     17 #include <mcld/Fragment/Relocation.h>
     18 #include <mcld/Support/MemoryRegion.h>
     19 #include <llvm/ADT/DenseMap.h>
     20 #include <llvm/ADT/DenseSet.h>
     21 #include <set>
     22 
     23 namespace mcld {
     24 
     25 class Input;
     26 class LDSection;
     27 class LDSymbol;
     28 class OutputRelocSection;
     29 
     30 /** \class MipsGOT
     31  *  \brief Mips Global Offset Table.
     32  */
     33 class MipsGOT : public GOT
     34 {
     35 public:
     36   MipsGOT(LDSection& pSection);
     37 
     38   /// Assign value to the GOT entry.
     39   virtual void setEntryValue(Fragment* entry, uint64_t pValue) = 0;
     40 
     41   /// Emit the global offset table.
     42   virtual uint64_t emit(MemoryRegion& pRegion) = 0;
     43 
     44   /// Address of _gp_disp symbol.
     45   uint64_t getGPDispAddress() const;
     46 
     47   void initializeScan(const Input& pInput);
     48   void finalizeScan(const Input& pInput);
     49 
     50   bool reserveLocalEntry(ResolveInfo& pInfo, int reloc,
     51                          Relocation::DWord pAddend);
     52   bool reserveGlobalEntry(ResolveInfo& pInfo);
     53 
     54   size_t getLocalNum() const;   ///< number of local symbols in primary GOT
     55   size_t getGlobalNum() const;  ///< total number of global symbols
     56 
     57   bool isPrimaryGOTConsumed();
     58 
     59   Fragment* consumeLocal();
     60   Fragment* consumeGlobal();
     61 
     62   uint64_t getGPAddr(const Input& pInput) const;
     63   uint64_t getGPRelOffset(const Input& pInput, const Fragment& pEntry) const;
     64 
     65   void recordGlobalEntry(const ResolveInfo* pInfo, Fragment* pEntry);
     66   Fragment* lookupGlobalEntry(const ResolveInfo* pInfo);
     67 
     68   void recordLocalEntry(const ResolveInfo* pInfo,
     69                         Relocation::DWord pAddend,
     70                         Fragment* pEntry);
     71   Fragment* lookupLocalEntry(const ResolveInfo* pInfo,
     72                              Relocation::DWord pAddend);
     73 
     74   /// hasGOT1 - return if this got section has any GOT1 entry
     75   bool hasGOT1() const;
     76 
     77   bool hasMultipleGOT() const;
     78 
     79   /// Create GOT entries and reserve dynrel entries.
     80   void finalizeScanning(OutputRelocSection& pRelDyn);
     81 
     82   /// Compare two symbols to define order in the .dynsym.
     83   bool dynSymOrderCompare(const LDSymbol* pX, const LDSymbol* pY) const;
     84 
     85 protected:
     86   /// Create GOT entry.
     87   virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent) = 0;
     88 
     89   /// Size of GOT entry.
     90   virtual size_t getEntrySize() const = 0;
     91 
     92   /// Reserve GOT header entries.
     93   virtual void reserveHeader() = 0;
     94 
     95 private:
     96   /** \class GOTMultipart
     97    *  \brief GOTMultipart counts local and global entries in the GOT.
     98    */
     99   struct GOTMultipart
    100   {
    101     GOTMultipart(size_t local = 0, size_t global = 0);
    102 
    103     typedef llvm::DenseSet<const Input*> InputSetType;
    104 
    105     size_t m_LocalNum;  ///< number of reserved local entries
    106     size_t m_GlobalNum; ///< number of reserved global entries
    107 
    108     size_t m_ConsumedLocal;       ///< consumed local entries
    109     size_t m_ConsumedGlobal;      ///< consumed global entries
    110 
    111     Fragment* m_pLastLocal;   ///< the last consumed local entry
    112     Fragment* m_pLastGlobal;  ///< the last consumed global entry
    113 
    114     InputSetType m_Inputs;
    115 
    116     bool isConsumed() const;
    117 
    118     void consumeLocal();
    119     void consumeGlobal();
    120   };
    121 
    122   /** \class LocalEntry
    123    *  \brief LocalEntry local GOT entry descriptor.
    124    */
    125   struct LocalEntry
    126   {
    127     const ResolveInfo* m_pInfo;
    128     Relocation::DWord  m_Addend;
    129     bool               m_IsGot16;
    130 
    131     LocalEntry(const ResolveInfo* pInfo,
    132                Relocation::DWord addend, bool isGot16);
    133 
    134     bool operator<(const LocalEntry &O) const;
    135   };
    136 
    137   typedef std::vector<GOTMultipart> MultipartListType;
    138 
    139   // Set of global symbols.
    140   typedef llvm::DenseSet<const ResolveInfo*> SymbolSetType;
    141   // Map of symbols. If value is true, the symbol is referenced
    142   // in the current input only. If value is false, the symbol
    143   // is referenced in the other modules merged to the current GOT.
    144   typedef llvm::DenseMap<const ResolveInfo*, bool> SymbolUniqueMapType;
    145 
    146   // Set of local symbols.
    147   typedef std::set<LocalEntry> LocalSymbolSetType;
    148 
    149   MultipartListType m_MultipartList;  ///< list of GOT's descriptors
    150   const Input* m_pInput;              ///< current input
    151 
    152   // Global symbols merged to the current GOT
    153   // except symbols from the current input.
    154   SymbolSetType m_MergedGlobalSymbols;
    155   // Global symbols from the current input.
    156   SymbolUniqueMapType m_InputGlobalSymbols;
    157   // Local symbols merged to the current GOT
    158   // except symbols from the current input.
    159   LocalSymbolSetType m_MergedLocalSymbols;
    160   // Local symbols from the current input.
    161   LocalSymbolSetType m_InputLocalSymbols;
    162 
    163   size_t m_CurrentGOTPart;
    164 
    165   typedef llvm::DenseMap<const LDSymbol*, unsigned> SymbolOrderMapType;
    166   SymbolOrderMapType m_SymbolOrderMap;
    167 
    168   void initGOTList();
    169 
    170   void changeInput();
    171   bool isGOTFull() const;
    172   void split();
    173   void reserve(size_t pNum);
    174 
    175 private:
    176   struct GotEntryKey
    177   {
    178     size_t m_GOTPage;
    179     const ResolveInfo* m_pInfo;
    180     Relocation::DWord m_Addend;
    181 
    182     bool operator<(const GotEntryKey& key) const
    183     {
    184       if (m_GOTPage != key.m_GOTPage)
    185         return m_GOTPage < key.m_GOTPage;
    186 
    187       if (m_pInfo != key.m_pInfo)
    188         return m_pInfo < key.m_pInfo;
    189 
    190       return m_Addend < key.m_Addend;
    191     }
    192   };
    193 
    194   typedef std::map<GotEntryKey, Fragment*> GotEntryMapType;
    195   GotEntryMapType m_GotLocalEntriesMap;
    196   GotEntryMapType m_GotGlobalEntriesMap;
    197 };
    198 
    199 /** \class Mips32GOT
    200  *  \brief Mips 32-bit Global Offset Table.
    201  */
    202 class Mips32GOT : public MipsGOT
    203 {
    204 public:
    205   Mips32GOT(LDSection& pSection);
    206 
    207 private:
    208   typedef GOT::Entry<4> Mips32GOTEntry;
    209 
    210   // MipsGOT
    211   virtual void setEntryValue(Fragment* entry, uint64_t pValue);
    212   virtual uint64_t emit(MemoryRegion& pRegion);
    213   virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent);
    214   virtual size_t getEntrySize() const;
    215   virtual void reserveHeader();
    216 };
    217 
    218 /** \class Mips64GOT
    219  *  \brief Mips 64-bit Global Offset Table.
    220  */
    221 class Mips64GOT : public MipsGOT
    222 {
    223 public:
    224   Mips64GOT(LDSection& pSection);
    225 
    226 private:
    227   typedef GOT::Entry<8> Mips64GOTEntry;
    228 
    229   // MipsGOT
    230   virtual void setEntryValue(Fragment* entry, uint64_t pValue);
    231   virtual uint64_t emit(MemoryRegion& pRegion);
    232   virtual Fragment* createEntry(uint64_t pValue, SectionData* pParent);
    233   virtual size_t getEntrySize() const;
    234   virtual void reserveHeader();
    235 };
    236 
    237 } // namespace of mcld
    238 
    239 #endif
    240 
    241