1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,194 @@ 1.4 +// Copyright (c) 2012, Google Inc. 1.5 +// All rights reserved. 1.6 +// 1.7 +// Redistribution and use in source and binary forms, with or without 1.8 +// modification, are permitted provided that the following conditions are 1.9 +// met: 1.10 +// 1.11 +// * Redistributions of source code must retain the above copyright 1.12 +// notice, this list of conditions and the following disclaimer. 1.13 +// * Redistributions in binary form must reproduce the above 1.14 +// copyright notice, this list of conditions and the following disclaimer 1.15 +// in the documentation and/or other materials provided with the 1.16 +// distribution. 1.17 +// * Neither the name of Google Inc. nor the names of its 1.18 +// contributors may be used to endorse or promote products derived from 1.19 +// this software without specific prior written permission. 1.20 +// 1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.32 + 1.33 +#include "common/linux/elfutils.h" 1.34 + 1.35 +#include <assert.h> 1.36 +#include <string.h> 1.37 + 1.38 +#include "common/linux/linux_libc_support.h" 1.39 +#include "common/linux/elfutils-inl.h" 1.40 + 1.41 +namespace google_breakpad { 1.42 + 1.43 +namespace { 1.44 + 1.45 +template<typename ElfClass> 1.46 +void FindElfClassSection(const char *elf_base, 1.47 + const char *section_name, 1.48 + typename ElfClass::Word section_type, 1.49 + const void **section_start, 1.50 + int *section_size) { 1.51 + typedef typename ElfClass::Ehdr Ehdr; 1.52 + typedef typename ElfClass::Shdr Shdr; 1.53 + 1.54 + assert(elf_base); 1.55 + assert(section_start); 1.56 + assert(section_size); 1.57 + 1.58 + assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0); 1.59 + 1.60 + const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base); 1.61 + assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass); 1.62 + 1.63 + const Shdr* sections = 1.64 + GetOffset<ElfClass,Shdr>(elf_header, elf_header->e_shoff); 1.65 + const Shdr* section_names = sections + elf_header->e_shstrndx; 1.66 + const char* names = 1.67 + GetOffset<ElfClass,char>(elf_header, section_names->sh_offset); 1.68 + const char *names_end = names + section_names->sh_size; 1.69 + 1.70 + const Shdr* section = 1.71 + FindElfSectionByName<ElfClass>(section_name, section_type, 1.72 + sections, names, names_end, 1.73 + elf_header->e_shnum); 1.74 + 1.75 + if (section != NULL && section->sh_size > 0) { 1.76 + *section_start = elf_base + section->sh_offset; 1.77 + *section_size = section->sh_size; 1.78 + } 1.79 +} 1.80 + 1.81 +template<typename ElfClass> 1.82 +void FindElfClassSegment(const char *elf_base, 1.83 + typename ElfClass::Word segment_type, 1.84 + const void **segment_start, 1.85 + int *segment_size) { 1.86 + typedef typename ElfClass::Ehdr Ehdr; 1.87 + typedef typename ElfClass::Phdr Phdr; 1.88 + 1.89 + assert(elf_base); 1.90 + assert(segment_start); 1.91 + assert(segment_size); 1.92 + 1.93 + assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0); 1.94 + 1.95 + const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base); 1.96 + assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass); 1.97 + 1.98 + const Phdr* phdrs = 1.99 + GetOffset<ElfClass,Phdr>(elf_header, elf_header->e_phoff); 1.100 + 1.101 + for (int i = 0; i < elf_header->e_phnum; ++i) { 1.102 + if (phdrs[i].p_type == segment_type) { 1.103 + *segment_start = elf_base + phdrs[i].p_offset; 1.104 + *segment_size = phdrs[i].p_filesz; 1.105 + return; 1.106 + } 1.107 + } 1.108 +} 1.109 + 1.110 +} // namespace 1.111 + 1.112 +bool IsValidElf(const void* elf_base) { 1.113 + return my_strncmp(reinterpret_cast<const char*>(elf_base), 1.114 + ELFMAG, SELFMAG) == 0; 1.115 +} 1.116 + 1.117 +int ElfClass(const void* elf_base) { 1.118 + const ElfW(Ehdr)* elf_header = 1.119 + reinterpret_cast<const ElfW(Ehdr)*>(elf_base); 1.120 + 1.121 + return elf_header->e_ident[EI_CLASS]; 1.122 +} 1.123 + 1.124 +bool FindElfSection(const void *elf_mapped_base, 1.125 + const char *section_name, 1.126 + uint32_t section_type, 1.127 + const void **section_start, 1.128 + int *section_size, 1.129 + int *elfclass) { 1.130 + assert(elf_mapped_base); 1.131 + assert(section_start); 1.132 + assert(section_size); 1.133 + 1.134 + *section_start = NULL; 1.135 + *section_size = 0; 1.136 + 1.137 + if (!IsValidElf(elf_mapped_base)) 1.138 + return false; 1.139 + 1.140 + int cls = ElfClass(elf_mapped_base); 1.141 + if (elfclass) { 1.142 + *elfclass = cls; 1.143 + } 1.144 + 1.145 + const char* elf_base = 1.146 + static_cast<const char*>(elf_mapped_base); 1.147 + 1.148 + if (cls == ELFCLASS32) { 1.149 + FindElfClassSection<ElfClass32>(elf_base, section_name, section_type, 1.150 + section_start, section_size); 1.151 + return *section_start != NULL; 1.152 + } else if (cls == ELFCLASS64) { 1.153 + FindElfClassSection<ElfClass64>(elf_base, section_name, section_type, 1.154 + section_start, section_size); 1.155 + return *section_start != NULL; 1.156 + } 1.157 + 1.158 + return false; 1.159 +} 1.160 + 1.161 +bool FindElfSegment(const void *elf_mapped_base, 1.162 + uint32_t segment_type, 1.163 + const void **segment_start, 1.164 + int *segment_size, 1.165 + int *elfclass) { 1.166 + assert(elf_mapped_base); 1.167 + assert(segment_start); 1.168 + assert(segment_size); 1.169 + 1.170 + *segment_start = NULL; 1.171 + *segment_size = 0; 1.172 + 1.173 + if (!IsValidElf(elf_mapped_base)) 1.174 + return false; 1.175 + 1.176 + int cls = ElfClass(elf_mapped_base); 1.177 + if (elfclass) { 1.178 + *elfclass = cls; 1.179 + } 1.180 + 1.181 + const char* elf_base = 1.182 + static_cast<const char*>(elf_mapped_base); 1.183 + 1.184 + if (cls == ELFCLASS32) { 1.185 + FindElfClassSegment<ElfClass32>(elf_base, segment_type, 1.186 + segment_start, segment_size); 1.187 + return *segment_start != NULL; 1.188 + } else if (cls == ELFCLASS64) { 1.189 + FindElfClassSegment<ElfClass64>(elf_base, segment_type, 1.190 + segment_start, segment_size); 1.191 + return *segment_start != NULL; 1.192 + } 1.193 + 1.194 + return false; 1.195 +} 1.196 + 1.197 +} // namespace google_breakpad