Home | History | Annotate | Download | only in include
      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