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
getELFHeaderSize()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.
less(AliasInfo p1,AliasInfo p2)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
getELFHeaderSize()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.
less(AliasInfo p1,AliasInfo p2)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