ELFReader.h revision f7ac0f19a1c8d0ad14bcf6456ce368b830fea886
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
26namespace mcld {
27
28//class Module;
29class IRBuilder;
30class SectionData;
31class LDSection;
32
33/** \class ELFReader
34 *  \brief ELFReader is a template scaffolding for partial specification.
35 */
36template<size_t BIT, bool LITTLEENDIAN>
37class ELFReader
38{ };
39
40/** \class ELFReader<32, true>
41 *  \brief ELFReader<32, true> is a 32-bit, little endian ELFReader.
42 */
43template<>
44class ELFReader<32, true> : public ELFReaderIF
45{
46public:
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
53public:
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
105private:
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 */
133template<>
134class ELFReader<64, true> : public ELFReaderIF
135{
136public:
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
143public:
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
195private:
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