Home | History | Annotate | Download | only in linux
      1 // Copyright (c) 2012, Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 #include "common/linux/elfutils.h"
     31 
     32 #include <assert.h>
     33 #include <string.h>
     34 
     35 #include "common/linux/linux_libc_support.h"
     36 #include "common/linux/elfutils-inl.h"
     37 
     38 namespace google_breakpad {
     39 
     40 namespace {
     41 
     42 template<typename ElfClass>
     43 void FindElfClassSection(const char *elf_base,
     44                          const char *section_name,
     45                          typename ElfClass::Word section_type,
     46                          const void **section_start,
     47                          size_t *section_size) {
     48   typedef typename ElfClass::Ehdr Ehdr;
     49   typedef typename ElfClass::Shdr Shdr;
     50 
     51   assert(elf_base);
     52   assert(section_start);
     53   assert(section_size);
     54 
     55   assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0);
     56 
     57   const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
     58   assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass);
     59 
     60   const Shdr* sections =
     61     GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
     62   const Shdr* section_names = sections + elf_header->e_shstrndx;
     63   const char* names =
     64     GetOffset<ElfClass, char>(elf_header, section_names->sh_offset);
     65   const char *names_end = names + section_names->sh_size;
     66 
     67   const Shdr* section =
     68     FindElfSectionByName<ElfClass>(section_name, section_type,
     69                                    sections, names, names_end,
     70                                    elf_header->e_shnum);
     71 
     72   if (section != NULL && section->sh_size > 0) {
     73     *section_start = elf_base + section->sh_offset;
     74     *section_size = section->sh_size;
     75   }
     76 }
     77 
     78 template<typename ElfClass>
     79 void FindElfClassSegment(const char *elf_base,
     80                          typename ElfClass::Word segment_type,
     81                          const void **segment_start,
     82                          size_t *segment_size) {
     83   typedef typename ElfClass::Ehdr Ehdr;
     84   typedef typename ElfClass::Phdr Phdr;
     85 
     86   assert(elf_base);
     87   assert(segment_start);
     88   assert(segment_size);
     89 
     90   assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0);
     91 
     92   const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
     93   assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass);
     94 
     95   const Phdr* phdrs =
     96     GetOffset<ElfClass, Phdr>(elf_header, elf_header->e_phoff);
     97 
     98   for (int i = 0; i < elf_header->e_phnum; ++i) {
     99     if (phdrs[i].p_type == segment_type) {
    100       *segment_start = elf_base + phdrs[i].p_offset;
    101       *segment_size = phdrs[i].p_filesz;
    102       return;
    103     }
    104   }
    105 }
    106 
    107 }  // namespace
    108 
    109 bool IsValidElf(const void* elf_base) {
    110   return my_strncmp(reinterpret_cast<const char*>(elf_base),
    111                     ELFMAG, SELFMAG) == 0;
    112 }
    113 
    114 int ElfClass(const void* elf_base) {
    115   const ElfW(Ehdr)* elf_header =
    116     reinterpret_cast<const ElfW(Ehdr)*>(elf_base);
    117 
    118   return elf_header->e_ident[EI_CLASS];
    119 }
    120 
    121 bool FindElfSection(const void *elf_mapped_base,
    122                     const char *section_name,
    123                     uint32_t section_type,
    124                     const void **section_start,
    125                     size_t *section_size,
    126                     int *elfclass) {
    127   assert(elf_mapped_base);
    128   assert(section_start);
    129   assert(section_size);
    130 
    131   *section_start = NULL;
    132   *section_size = 0;
    133 
    134   if (!IsValidElf(elf_mapped_base))
    135     return false;
    136 
    137   int cls = ElfClass(elf_mapped_base);
    138   if (elfclass) {
    139     *elfclass = cls;
    140   }
    141 
    142   const char* elf_base =
    143     static_cast<const char*>(elf_mapped_base);
    144 
    145   if (cls == ELFCLASS32) {
    146     FindElfClassSection<ElfClass32>(elf_base, section_name, section_type,
    147                                     section_start, section_size);
    148     return *section_start != NULL;
    149   } else if (cls == ELFCLASS64) {
    150     FindElfClassSection<ElfClass64>(elf_base, section_name, section_type,
    151                                     section_start, section_size);
    152     return *section_start != NULL;
    153   }
    154 
    155   return false;
    156 }
    157 
    158 bool FindElfSegment(const void *elf_mapped_base,
    159                     uint32_t segment_type,
    160                     const void **segment_start,
    161                     size_t *segment_size,
    162                     int *elfclass) {
    163   assert(elf_mapped_base);
    164   assert(segment_start);
    165   assert(segment_size);
    166 
    167   *segment_start = NULL;
    168   *segment_size = 0;
    169 
    170   if (!IsValidElf(elf_mapped_base))
    171     return false;
    172 
    173   int cls = ElfClass(elf_mapped_base);
    174   if (elfclass) {
    175     *elfclass = cls;
    176   }
    177 
    178   const char* elf_base =
    179     static_cast<const char*>(elf_mapped_base);
    180 
    181   if (cls == ELFCLASS32) {
    182     FindElfClassSegment<ElfClass32>(elf_base, segment_type,
    183                                     segment_start, segment_size);
    184     return *segment_start != NULL;
    185   } else if (cls == ELFCLASS64) {
    186     FindElfClassSegment<ElfClass64>(elf_base, segment_type,
    187                                     segment_start, segment_size);
    188     return *segment_start != NULL;
    189   }
    190 
    191   return false;
    192 }
    193 
    194 }  // namespace google_breakpad
    195