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