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 <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