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