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: 58 ELFHeader() { } 59 60 public: 61 byte_t getClass() const { 62 return e_ident[EI_CLASS]; 63 } 64 65 byte_t getEndianness() const { 66 return e_ident[EI_DATA]; 67 } 68 69 byte_t getVersionFromIdent() const { 70 return e_ident[EI_VERSION]; 71 } 72 73 byte_t getOSABI() const { 74 return e_ident[EI_OSABI]; 75 } 76 77 byte_t getABIVersion() const { 78 return e_ident[EI_ABIVERSION]; 79 } 80 81 bool is32bit() const { 82 return e_ident[EI_CLASS] == ELFCLASS32; 83 } 84 85 bool is64bit() const { 86 return e_ident[EI_CLASS] == ELFCLASS64; 87 } 88 89 bool isBigEndian() const { 90 return e_ident[EI_DATA] == ELFDATA2MSB; 91 } 92 93 bool isLittleEndian() const { 94 return e_ident[EI_DATA] == ELFDATA2LSB; 95 } 96 97 half_t getObjectType() const { 98 return e_type; 99 } 100 101 half_t getMachine() const { 102 return e_machine; 103 } 104 105 word_t getVersion() const { 106 return e_version; 107 } 108 109 addr_t getEntryAddress() const { 110 return e_entry; 111 } 112 113 offset_t getProgramHeaderTableOffset() const { 114 return e_phoff; 115 } 116 117 offset_t getSectionHeaderTableOffset() const { 118 return e_shoff; 119 } 120 121 word_t getFlags() const { 122 return e_flags; 123 } 124 125 half_t getELFHeaderSize() const { 126 return e_ehsize; 127 } 128 129 half_t getProgramHeaderEntrySize() const { 130 return e_phentsize; 131 } 132 133 half_t getProgramHeaderNum() const { 134 return e_phnum; 135 } 136 137 half_t getSectionHeaderEntrySize() const { 138 return e_shentsize; 139 } 140 141 half_t getSectionHeaderNum() const { 142 return e_shnum; 143 } 144 145 half_t getStringSectionIndex() const { 146 return e_shstrndx; 147 } 148 149 template <typename Archiver> 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 173 bool isValid() const { 174 return (isValidELFIdent() && isCompatibleHeaderSize()); 175 } 176 177 private: 178 template <typename Archiver> 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 201 bool isValidMagicWord() const { 202 return (memcmp(e_ident, "\x7f" "ELF", 4) == 0); 203 } 204 205 bool isValidClass() const { 206 return ((Bitwidth == 32 && is32bit()) || 207 (Bitwidth == 64 && is64bit())); 208 } 209 210 bool isValidEndianness() const { 211 return (isBigEndian() || isLittleEndian()); 212 } 213 214 bool isValidHeaderVersion() const { 215 return (getVersion() == EV_CURRENT); 216 } 217 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 227 bool isValidELFIdent() const { 228 return (isValidMagicWord() && 229 isValidClass() && 230 isValidEndianness() && 231 isValidHeaderVersion() && 232 isUnusedZeroedPadding()); 233 } 234 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