| /* |
| * Copyright 2011, The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef ELF_HEADER_H |
| #define ELF_HEADER_H |
| |
| #include "ELFTypes.h" |
| #include "ELF.h" |
| |
| #include <llvm/ADT/OwningPtr.h> |
| |
| #include <string.h> |
| |
| class ELFHeaderHelperMixin { |
| protected: |
| static char const *getClassStr(int clazz); |
| static char const *getEndiannessStr(int endianness); |
| static char const *getOSABIStr(int abi); |
| static char const *getObjectTypeStr(uint16_t type); |
| static char const *getMachineStr(uint16_t machine); |
| static char const *getVersionStr(uint32_t version); |
| }; |
| |
| template <unsigned Bitwidth> |
| class ELFHeader : private ELFHeaderHelperMixin { |
| public: |
| ELF_TYPE_INTRO_TO_TEMPLATE_SCOPE(Bitwidth); |
| |
| protected: |
| byte_t e_ident[EI_NIDENT]; |
| half_t e_type; |
| half_t e_machine; |
| word_t e_version; |
| addr_t e_entry; |
| offset_t e_phoff; |
| offset_t e_shoff; |
| word_t e_flags; |
| half_t e_ehsize; |
| half_t e_phentsize; |
| half_t e_phnum; |
| half_t e_shentsize; |
| half_t e_shnum; |
| half_t e_shstrndx; |
| |
| protected: |
| ELFHeader() { } |
| |
| public: |
| byte_t getClass() const { |
| return e_ident[EI_CLASS]; |
| } |
| |
| byte_t getEndianness() const { |
| return e_ident[EI_DATA]; |
| } |
| |
| byte_t getVersionFromIdent() const { |
| return e_ident[EI_VERSION]; |
| } |
| |
| byte_t getOSABI() const { |
| return e_ident[EI_OSABI]; |
| } |
| |
| byte_t getABIVersion() const { |
| return e_ident[EI_ABIVERSION]; |
| } |
| |
| bool is32bit() const { |
| return e_ident[EI_CLASS] == ELFCLASS32; |
| } |
| |
| bool is64bit() const { |
| return e_ident[EI_CLASS] == ELFCLASS64; |
| } |
| |
| bool isBigEndian() const { |
| return e_ident[EI_DATA] == ELFDATA2MSB; |
| } |
| |
| bool isLittleEndian() const { |
| return e_ident[EI_DATA] == ELFDATA2LSB; |
| } |
| |
| half_t getObjectType() const { |
| return e_type; |
| } |
| |
| half_t getMachine() const { |
| return e_machine; |
| } |
| |
| word_t getVersion() const { |
| return e_version; |
| } |
| |
| addr_t getEntryAddress() const { |
| return e_entry; |
| } |
| |
| offset_t getProgramHeaderTableOffset() const { |
| return e_phoff; |
| } |
| |
| offset_t getSectionHeaderTableOffset() const { |
| return e_shoff; |
| } |
| |
| word_t getFlags() const { |
| return e_flags; |
| } |
| |
| half_t getELFHeaderSize() const { |
| return e_ehsize; |
| } |
| |
| half_t getProgramHeaderEntrySize() const { |
| return e_phentsize; |
| } |
| |
| half_t getProgramHeaderNum() const { |
| return e_phnum; |
| } |
| |
| half_t getSectionHeaderEntrySize() const { |
| return e_shentsize; |
| } |
| |
| half_t getSectionHeaderNum() const { |
| return e_shnum; |
| } |
| |
| half_t getStringSectionIndex() const { |
| return e_shstrndx; |
| } |
| |
| template <typename Archiver> |
| static ELFHeader *read(Archiver &AR) { |
| if (!AR) { |
| // Archiver is in bad state before calling read function. |
| // Return NULL and do nothing. |
| return 0; |
| } |
| |
| llvm::OwningPtr<ELFHeader> header(new ELFHeader()); |
| if (!header->serialize(AR)) { |
| // Unable to read the structure. Return NULL. |
| return 0; |
| } |
| |
| if (!header->isValid()) { |
| // Header read from archiver is not valid. Return NULL. |
| return 0; |
| } |
| |
| return header.take(); |
| } |
| |
| void print(); |
| |
| bool isValid() const { |
| return (isValidELFIdent() && isCompatibleHeaderSize()); |
| } |
| |
| private: |
| template <typename Archiver> |
| bool serialize(Archiver &AR) { |
| AR.prologue(TypeTraits<ELFHeaderTy>::size); |
| |
| AR & e_ident; |
| AR & e_type; |
| AR & e_machine; |
| AR & e_version; |
| AR & e_entry; |
| AR & e_phoff; |
| AR & e_shoff; |
| AR & e_flags; |
| AR & e_ehsize; |
| AR & e_phentsize; |
| AR & e_phnum; |
| AR & e_shentsize; |
| AR & e_shnum; |
| AR & e_shstrndx; |
| |
| AR.epilogue(TypeTraits<ELFHeaderTy>::size); |
| return AR; |
| } |
| |
| bool isValidMagicWord() const { |
| return (memcmp(e_ident, "\x7f" "ELF", 4) == 0); |
| } |
| |
| bool isValidClass() const { |
| return ((Bitwidth == 32 && is32bit()) || |
| (Bitwidth == 64 && is64bit())); |
| } |
| |
| bool isValidEndianness() const { |
| return (isBigEndian() || isLittleEndian()); |
| } |
| |
| bool isValidHeaderVersion() const { |
| return (getVersion() == EV_CURRENT); |
| } |
| |
| bool isUnusedZeroedPadding() const { |
| for (size_t i = EI_PAD; i < EI_NIDENT; ++i) { |
| if (e_ident[i] != 0) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| bool isValidELFIdent() const { |
| return (isValidMagicWord() && |
| isValidClass() && |
| isValidEndianness() && |
| isValidHeaderVersion() && |
| isUnusedZeroedPadding()); |
| } |
| |
| bool isCompatibleHeaderSize() const { |
| return ( |
| (e_ehsize == TypeTraits<ELFHeaderTy>::size) && |
| (e_phnum == 0 || e_phentsize == TypeTraits<ELFProgramHeaderTy>::size) && |
| (e_shnum == 0 || e_shentsize == TypeTraits<ELFSectionHeaderTy>::size)); |
| } |
| }; |
| |
| #include "impl/ELFHeader.hxx" |
| |
| #endif // ELF_HEADER_H |