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