Home | History | Annotate | Download | only in LD
      1 //===- ELFReader.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 MCLD_LD_ELFREADER_H_
     10 #define MCLD_LD_ELFREADER_H_
     11 
     12 #include "mcld/LD/ELFReaderIf.h"
     13 #include "mcld/LD/LDSymbol.h"
     14 #include "mcld/LD/ResolveInfo.h"
     15 #include "mcld/Target/GNULDBackend.h"
     16 
     17 #include <llvm/ADT/StringRef.h>
     18 #include <llvm/Support/ELF.h>
     19 #include <llvm/Support/Host.h>
     20 
     21 namespace mcld {
     22 
     23 class IRBuilder;
     24 class LDSection;
     25 class SectionData;
     26 
     27 /** \class ELFReader
     28  *  \brief ELFReader is a template scaffolding for partial specification.
     29  */
     30 template <size_t BIT, bool LITTLEENDIAN>
     31 class ELFReader {};
     32 
     33 /** \class ELFReader<32, true>
     34  *  \brief ELFReader<32, true> is a 32-bit, little endian ELFReader.
     35  */
     36 template <>
     37 class ELFReader<32, true> : public ELFReaderIF {
     38  public:
     39   typedef llvm::ELF::Elf32_Ehdr ELFHeader;
     40   typedef llvm::ELF::Elf32_Shdr SectionHeader;
     41   typedef llvm::ELF::Elf32_Sym Symbol;
     42   typedef llvm::ELF::Elf32_Rel Rel;
     43   typedef llvm::ELF::Elf32_Rela Rela;
     44 
     45  public:
     46   explicit ELFReader(GNULDBackend& pBackend);
     47 
     48   ~ELFReader();
     49 
     50   /// ELFHeaderSize - return the size of the ELFHeader
     51   size_t getELFHeaderSize() const { return sizeof(ELFHeader); }
     52 
     53   /// isELF - is this a ELF file
     54   bool isELF(const void* pELFHeader) const;
     55 
     56   /// isMyEndian - is this ELF file in the same endian to me?
     57   bool isMyEndian(const void* pELFHeader) const;
     58 
     59   /// isMyMachine - is this ELF file generated for the same machine.
     60   bool isMyMachine(const void* pELFHeader) const;
     61 
     62   /// fileType - the file type of this file
     63   Input::Type fileType(const void* pELFHeader) const;
     64 
     65   /// readSectionHeaders - read ELF section header table and create LDSections
     66   bool readSectionHeaders(Input& pInput, const void* pELFHeader) const;
     67 
     68   /// readRegularSection - read a regular section and create fragments.
     69   bool readRegularSection(Input& pInput, SectionData& pSD) const;
     70 
     71   /// readSymbols - read ELF symbols and create LDSymbol
     72   bool readSymbols(Input& pInput,
     73                    IRBuilder& pBuilder,
     74                    llvm::StringRef pRegion,
     75                    const char* StrTab) const;
     76 
     77   /// readSignature - read a symbol from the given Input and index in symtab
     78   /// This is used to get the signature of a group section.
     79   ResolveInfo* readSignature(Input& pInput,
     80                              LDSection& pSymTab,
     81                              uint32_t pSymIdx) const;
     82 
     83   /// readRela - read ELF rela and create Relocation
     84   bool readRela(Input& pInput,
     85                 LDSection& pSection,
     86                 llvm::StringRef pRegion) const;
     87 
     88   /// readRel - read ELF rel and create Relocation
     89   bool readRel(Input& pInput,
     90                LDSection& pSection,
     91                llvm::StringRef pRegion) const;
     92 
     93   /// readDynamic - read ELF .dynamic in input dynobj
     94   bool readDynamic(Input& pInput) const;
     95 
     96  private:
     97   struct AliasInfo {
     98     LDSymbol* pt_alias;  /// potential alias
     99     uint64_t ld_value;
    100     ResolveInfo::Binding ld_binding;
    101   };
    102 
    103   /// comparison function to sort symbols for analyzing weak alias.
    104   /// sort symbols by symbol value and then weak before strong.
    105   static bool less(AliasInfo p1, AliasInfo p2) {
    106     if (p1.ld_value != p2.ld_value)
    107       return (p1.ld_value < p2.ld_value);
    108     if (p1.ld_binding != p2.ld_binding) {
    109       if (ResolveInfo::Weak == p1.ld_binding)
    110         return true;
    111       else if (ResolveInfo::Weak == p2.ld_binding)
    112         return false;
    113     }
    114     return p1.pt_alias->str() < p2.pt_alias->str();
    115   }
    116 };
    117 
    118 /** \class ELFReader<64, true>
    119  *  \brief ELFReader<64, true> is a 64-bit, little endian ELFReader.
    120  */
    121 template <>
    122 class ELFReader<64, true> : public ELFReaderIF {
    123  public:
    124   typedef llvm::ELF::Elf64_Ehdr ELFHeader;
    125   typedef llvm::ELF::Elf64_Shdr SectionHeader;
    126   typedef llvm::ELF::Elf64_Sym Symbol;
    127   typedef llvm::ELF::Elf64_Rel Rel;
    128   typedef llvm::ELF::Elf64_Rela Rela;
    129 
    130  public:
    131   explicit ELFReader(GNULDBackend& pBackend);
    132 
    133   ~ELFReader();
    134 
    135   /// ELFHeaderSize - return the size of the ELFHeader
    136   size_t getELFHeaderSize() const { return sizeof(ELFHeader); }
    137 
    138   /// isELF - is this a ELF file
    139   bool isELF(const void* pELFHeader) const;
    140 
    141   /// isMyEndian - is this ELF file in the same endian to me?
    142   bool isMyEndian(const void* pELFHeader) const;
    143 
    144   /// isMyMachine - is this ELF file generated for the same machine.
    145   bool isMyMachine(const void* pELFHeader) const;
    146 
    147   /// fileType - the file type of this file
    148   Input::Type fileType(const void* pELFHeader) const;
    149 
    150   /// readSectionHeaders - read ELF section header table and create LDSections
    151   bool readSectionHeaders(Input& pInput, const void* pELFHeader) const;
    152 
    153   /// readRegularSection - read a regular section and create fragments.
    154   bool readRegularSection(Input& pInput, SectionData& pSD) const;
    155 
    156   /// readSymbols - read ELF symbols and create LDSymbol
    157   bool readSymbols(Input& pInput,
    158                    IRBuilder& pBuilder,
    159                    llvm::StringRef pRegion,
    160                    const char* StrTab) const;
    161 
    162   /// readSignature - read a symbol from the given Input and index in symtab
    163   /// This is used to get the signature of a group section.
    164   ResolveInfo* readSignature(Input& pInput,
    165                              LDSection& pSymTab,
    166                              uint32_t pSymIdx) const;
    167 
    168   /// readRela - read ELF rela and create Relocation
    169   bool readRela(Input& pInput,
    170                 LDSection& pSection,
    171                 llvm::StringRef pRegion) const;
    172 
    173   /// readRel - read ELF rel and create Relocation
    174   bool readRel(Input& pInput,
    175                LDSection& pSection,
    176                llvm::StringRef pRegion) const;
    177 
    178   /// readDynamic - read ELF .dynamic in input dynobj
    179   bool readDynamic(Input& pInput) const;
    180 
    181  private:
    182   struct AliasInfo {
    183     LDSymbol* pt_alias;  /// potential alias
    184     uint64_t ld_value;
    185     ResolveInfo::Binding ld_binding;
    186   };
    187 
    188   /// comparison function to sort symbols for analyzing weak alias.
    189   /// sort symbols by symbol value and then weak before strong.
    190   static bool less(AliasInfo p1, AliasInfo p2) {
    191     if (p1.ld_value != p2.ld_value)
    192       return (p1.ld_value < p2.ld_value);
    193     if (p1.ld_binding != p2.ld_binding) {
    194       if (ResolveInfo::Weak == p1.ld_binding)
    195         return true;
    196       else if (ResolveInfo::Weak == p2.ld_binding)
    197         return false;
    198     }
    199     return p1.pt_alias->str() < p2.pt_alias->str();
    200   }
    201 };
    202 
    203 }  // namespace mcld
    204 
    205 #endif  // MCLD_LD_ELFREADER_H_
    206