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 <memory>
24 #include <string.h>
25 
26 class ELFHeaderHelperMixin {
27 protected:
28   static char const *getClassStr(int clazz);
29   static char const *getEndiannessStr(int endianness);
30   static char const *getOSABIStr(int abi);
31   static char const *getObjectTypeStr(uint16_t type);
32   static char const *getMachineStr(uint16_t machine);
33   static char const *getVersionStr(uint32_t version);
34 };
35 
36 template <unsigned Bitwidth>
37 class ELFHeader : private ELFHeaderHelperMixin {
38 public:
39   ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth);
40 
41 protected:
42   byte_t   e_ident[EI_NIDENT];
43   half_t   e_type;
44   half_t   e_machine;
45   word_t   e_version;
46   addr_t   e_entry;
47   offset_t e_phoff;
48   offset_t e_shoff;
49   word_t   e_flags;
50   half_t   e_ehsize;
51   half_t   e_phentsize;
52   half_t   e_phnum;
53   half_t   e_shentsize;
54   half_t   e_shnum;
55   half_t   e_shstrndx;
56 
57 protected:
ELFHeader()58   ELFHeader() { }
59 
60 public:
getClass()61   byte_t getClass() const {
62     return e_ident[EI_CLASS];
63   }
64 
getEndianness()65   byte_t getEndianness() const {
66     return e_ident[EI_DATA];
67   }
68 
getVersionFromIdent()69   byte_t getVersionFromIdent() const {
70     return e_ident[EI_VERSION];
71   }
72 
getOSABI()73   byte_t getOSABI() const {
74     return e_ident[EI_OSABI];
75   }
76 
getABIVersion()77   byte_t getABIVersion() const {
78     return e_ident[EI_ABIVERSION];
79   }
80 
is32bit()81   bool is32bit() const {
82     return e_ident[EI_CLASS] == ELFCLASS32;
83   }
84 
is64bit()85   bool is64bit() const {
86     return e_ident[EI_CLASS] == ELFCLASS64;
87   }
88 
isBigEndian()89   bool isBigEndian() const {
90     return e_ident[EI_DATA] == ELFDATA2MSB;
91   }
92 
isLittleEndian()93   bool isLittleEndian() const {
94     return e_ident[EI_DATA] == ELFDATA2LSB;
95   }
96 
getObjectType()97   half_t getObjectType() const {
98     return e_type;
99   }
100 
getMachine()101   half_t getMachine() const {
102     return e_machine;
103   }
104 
getVersion()105   word_t getVersion() const {
106     return e_version;
107   }
108 
getEntryAddress()109   addr_t getEntryAddress() const {
110     return e_entry;
111   }
112 
getProgramHeaderTableOffset()113   offset_t getProgramHeaderTableOffset() const {
114     return e_phoff;
115   }
116 
getSectionHeaderTableOffset()117   offset_t getSectionHeaderTableOffset() const {
118     return e_shoff;
119   }
120 
getFlags()121   word_t getFlags() const {
122     return e_flags;
123   }
124 
getELFHeaderSize()125   half_t getELFHeaderSize() const {
126     return e_ehsize;
127   }
128 
getProgramHeaderEntrySize()129   half_t getProgramHeaderEntrySize() const {
130     return e_phentsize;
131   }
132 
getProgramHeaderNum()133   half_t getProgramHeaderNum() const {
134     return e_phnum;
135   }
136 
getSectionHeaderEntrySize()137   half_t getSectionHeaderEntrySize() const {
138     return e_shentsize;
139   }
140 
getSectionHeaderNum()141   half_t getSectionHeaderNum() const {
142     return e_shnum;
143   }
144 
getStringSectionIndex()145   half_t getStringSectionIndex() const {
146     return e_shstrndx;
147   }
148 
149   template <typename Archiver>
read(Archiver & AR)150   static ELFHeader *read(Archiver &AR) {
151     if (!AR) {
152       // Archiver is in bad state before calling read function.
153       // Return NULL and do nothing.
154       return 0;
155     }
156 
157     std::unique_ptr<ELFHeader> header(new ELFHeader());
158     if (!header->serialize(AR)) {
159       // Unable to read the structure.  Return NULL.
160       return 0;
161     }
162 
163     if (!header->isValid()) {
164       // Header read from archiver is not valid.  Return NULL.
165       return 0;
166     }
167 
168     return header.release();
169   }
170 
171   void print();
172 
isValid()173   bool isValid() const {
174     return (isValidELFIdent() && isCompatibleHeaderSize());
175   }
176 
177 private:
178   template <typename Archiver>
serialize(Archiver & AR)179   bool serialize(Archiver &AR) {
180     AR.prologue(TypeTraits<ELFHeaderTy>::size);
181 
182     AR & e_ident;
183     AR & e_type;
184     AR & e_machine;
185     AR & e_version;
186     AR & e_entry;
187     AR & e_phoff;
188     AR & e_shoff;
189     AR & e_flags;
190     AR & e_ehsize;
191     AR & e_phentsize;
192     AR & e_phnum;
193     AR & e_shentsize;
194     AR & e_shnum;
195     AR & e_shstrndx;
196 
197     AR.epilogue(TypeTraits<ELFHeaderTy>::size);
198     return AR;
199   }
200 
isValidMagicWord()201   bool isValidMagicWord() const {
202     return (memcmp(e_ident, "\x7f" "ELF", 4) == 0);
203   }
204 
isValidClass()205   bool isValidClass() const {
206     return ((Bitwidth == 32 && is32bit()) ||
207             (Bitwidth == 64 && is64bit()));
208   }
209 
isValidEndianness()210   bool isValidEndianness() const {
211     return (isBigEndian() || isLittleEndian());
212   }
213 
isValidHeaderVersion()214   bool isValidHeaderVersion() const {
215     return (getVersion() == EV_CURRENT);
216   }
217 
isUnusedZeroedPadding()218   bool isUnusedZeroedPadding() const {
219     for (size_t i = EI_PAD; i < EI_NIDENT; ++i) {
220       if (e_ident[i] != 0) {
221         return false;
222       }
223     }
224     return true;
225   }
226 
isValidELFIdent()227   bool isValidELFIdent() const {
228     return (isValidMagicWord() &&
229             isValidClass() &&
230             isValidEndianness() &&
231             isValidHeaderVersion() &&
232             isUnusedZeroedPadding());
233   }
234 
isCompatibleHeaderSize()235   bool isCompatibleHeaderSize() const {
236     return (
237       (e_ehsize == TypeTraits<ELFHeaderTy>::size) &&
238       (e_phnum == 0 || e_phentsize == TypeTraits<ELFProgramHeaderTy>::size) &&
239       (e_shnum == 0 || e_shentsize == TypeTraits<ELFSectionHeaderTy>::size));
240   }
241 };
242 
243 #include "impl/ELFHeader.hxx"
244 
245 #endif // ELF_HEADER_H
246