• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ELF_HEADER_H
18 #define ELF_HEADER_H
19 
20 #include "ELFTypes.h"
21 #include "ELF.h"
22 
23 #include <llvm/ADT/OwningPtr.h>
24 
25 #include <string.h>
26 
27 class ELFHeaderHelperMixin {
28 protected:
29   static char const *getClassStr(int clazz);
30   static char const *getEndiannessStr(int endianness);
31   static char const *getOSABIStr(int abi);
32   static char const *getObjectTypeStr(uint16_t type);
33   static char const *getMachineStr(uint16_t machine);
34   static char const *getVersionStr(uint32_t version);
35 };
36 
37 template <unsigned Bitwidth>
38 class ELFHeader : private ELFHeaderHelperMixin {
39 public:
40   ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
41 
42 protected:
43   byte_t   e_ident[EI_NIDENT];
44   half_t   e_type;
45   half_t   e_machine;
46   word_t   e_version;
47   addr_t   e_entry;
48   offset_t e_phoff;
49   offset_t e_shoff;
50   word_t   e_flags;
51   half_t   e_ehsize;
52   half_t   e_phentsize;
53   half_t   e_phnum;
54   half_t   e_shentsize;
55   half_t   e_shnum;
56   half_t   e_shstrndx;
57 
58 protected:
ELFHeader()59   ELFHeader() { }
60 
61 public:
getClass()62   byte_t getClass() const {
63     return e_ident[EI_CLASS];
64   }
65 
getEndianness()66   byte_t getEndianness() const {
67     return e_ident[EI_DATA];
68   }
69 
getVersionFromIdent()70   byte_t getVersionFromIdent() const {
71     return e_ident[EI_VERSION];
72   }
73 
getOSABI()74   byte_t getOSABI() const {
75     return e_ident[EI_OSABI];
76   }
77 
getABIVersion()78   byte_t getABIVersion() const {
79     return e_ident[EI_ABIVERSION];
80   }
81 
is32bit()82   bool is32bit() const {
83     return e_ident[EI_CLASS] == ELFCLASS32;
84   }
85 
is64bit()86   bool is64bit() const {
87     return e_ident[EI_CLASS] == ELFCLASS64;
88   }
89 
isBigEndian()90   bool isBigEndian() const {
91     return e_ident[EI_DATA] == ELFDATA2MSB;
92   }
93 
isLittleEndian()94   bool isLittleEndian() const {
95     return e_ident[EI_DATA] == ELFDATA2LSB;
96   }
97 
getObjectType()98   half_t getObjectType() const {
99     return e_type;
100   }
101 
getMachine()102   half_t getMachine() const {
103     return e_machine;
104   }
105 
getVersion()106   word_t getVersion() const {
107     return e_version;
108   }
109 
getEntryAddress()110   addr_t getEntryAddress() const {
111     return e_entry;
112   }
113 
getProgramHeaderTableOffset()114   offset_t getProgramHeaderTableOffset() const {
115     return e_phoff;
116   }
117 
getSectionHeaderTableOffset()118   offset_t getSectionHeaderTableOffset() const {
119     return e_shoff;
120   }
121 
getFlags()122   word_t getFlags() const {
123     return e_flags;
124   }
125 
getELFHeaderSize()126   half_t getELFHeaderSize() const {
127     return e_ehsize;
128   }
129 
getProgramHeaderEntrySize()130   half_t getProgramHeaderEntrySize() const {
131     return e_phentsize;
132   }
133 
getProgramHeaderNum()134   half_t getProgramHeaderNum() const {
135     return e_phnum;
136   }
137 
getSectionHeaderEntrySize()138   half_t getSectionHeaderEntrySize() const {
139     return e_shentsize;
140   }
141 
getSectionHeaderNum()142   half_t getSectionHeaderNum() const {
143     return e_shnum;
144   }
145 
getStringSectionIndex()146   half_t getStringSectionIndex() const {
147     return e_shstrndx;
148   }
149 
150   template <typename Archiver>
read(Archiver & AR)151   static ELFHeader *read(Archiver &AR) {
152     if (!AR) {
153       // Archiver is in bad state before calling read function.
154       // Return NULL and do nothing.
155       return 0;
156     }
157 
158     llvm::OwningPtr<ELFHeader> header(new ELFHeader());
159     if (!header->serialize(AR)) {
160       // Unable to read the structure.  Return NULL.
161       return 0;
162     }
163 
164     if (!header->isValid()) {
165       // Header read from archiver is not valid.  Return NULL.
166       return 0;
167     }
168 
169     return header.take();
170   }
171 
172   void print();
173 
isValid()174   bool isValid() const {
175     return (isValidELFIdent() && isCompatibleHeaderSize());
176   }
177 
178 private:
179   template <typename Archiver>
serialize(Archiver & AR)180   bool serialize(Archiver &AR) {
181     AR.prologue(TypeTraits<ELFHeaderTy>::size);
182 
183     AR & e_ident;
184     AR & e_type;
185     AR & e_machine;
186     AR & e_version;
187     AR & e_entry;
188     AR & e_phoff;
189     AR & e_shoff;
190     AR & e_flags;
191     AR & e_ehsize;
192     AR & e_phentsize;
193     AR & e_phnum;
194     AR & e_shentsize;
195     AR & e_shnum;
196     AR & e_shstrndx;
197 
198     AR.epilogue(TypeTraits<ELFHeaderTy>::size);
199     return AR;
200   }
201 
isValidMagicWord()202   bool isValidMagicWord() const {
203     return (memcmp(e_ident, "\x7f" "ELF", 4) == 0);
204   }
205 
isValidClass()206   bool isValidClass() const {
207     return ((Bitwidth == 32 && is32bit()) ||
208             (Bitwidth == 64 && is64bit()));
209   }
210 
isValidEndianness()211   bool isValidEndianness() const {
212     return (isBigEndian() || isLittleEndian());
213   }
214 
isValidHeaderVersion()215   bool isValidHeaderVersion() const {
216     return (getVersion() == EV_CURRENT);
217   }
218 
isUnusedZeroedPadding()219   bool isUnusedZeroedPadding() const {
220     for (size_t i = EI_PAD; i < EI_NIDENT; ++i) {
221       if (e_ident[i] != 0) {
222         return false;
223       }
224     }
225     return true;
226   }
227 
isValidELFIdent()228   bool isValidELFIdent() const {
229     return (isValidMagicWord() &&
230             isValidClass() &&
231             isValidEndianness() &&
232             isValidHeaderVersion() &&
233             isUnusedZeroedPadding());
234   }
235 
isCompatibleHeaderSize()236   bool isCompatibleHeaderSize() const {
237     return (
238       (e_ehsize == TypeTraits<ELFHeaderTy>::size) &&
239       (e_phnum == 0 || e_phentsize == TypeTraits<ELFProgramHeaderTy>::size) &&
240       (e_shnum == 0 || e_shentsize == TypeTraits<ELFSectionHeaderTy>::size));
241   }
242 };
243 
244 #include "impl/ELFHeader.hxx"
245 
246 #endif // ELF_HEADER_H
247