diff options
author | ted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2012-07-18 13:44:34 +0000 |
---|---|---|
committer | ted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2012-07-18 13:44:34 +0000 |
commit | 972be40f1ff23f9fddd50f14350be6fd0355fe0f (patch) | |
tree | 715a3973c8444b2688b7c15f7bcdfa0ba5d93d46 /src | |
parent | Allow the crash generation server to be initialized with a handle instead of... (diff) | |
download | breakpad-972be40f1ff23f9fddd50f14350be6fd0355fe0f.tar.xz |
Move some ELF-handling bits from file_id.cc to elfutils.{h,cc}
R=mark at https://breakpad.appspot.com/392002/
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@986 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src')
-rw-r--r-- | src/common/linux/elfutils.cc | 122 | ||||
-rw-r--r-- | src/common/linux/elfutils.h | 81 | ||||
-rw-r--r-- | src/common/linux/file_id.cc | 105 |
3 files changed, 204 insertions, 104 deletions
diff --git a/src/common/linux/elfutils.cc b/src/common/linux/elfutils.cc new file mode 100644 index 00000000..2fd5c1ff --- /dev/null +++ b/src/common/linux/elfutils.cc @@ -0,0 +1,122 @@ +// Copyright (c) 2012, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "common/linux/elfutils.h" + +#include <assert.h> +#include <string.h> + +#include "common/linux/linux_libc_support.h" + +namespace google_breakpad { + +namespace { + +template<typename ElfClass> +void FindElfClassSection(const char *elf_base, + const char *section_name, + uint32_t section_type, + const void **section_start, + int *section_size) { + typedef typename ElfClass::Ehdr Ehdr; + typedef typename ElfClass::Shdr Shdr; + + assert(elf_base); + assert(section_start); + assert(section_size); + + assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0); + + int name_len = my_strlen(section_name); + + const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base); + assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass); + + const Shdr* sections = + reinterpret_cast<const Shdr*>(elf_base + elf_header->e_shoff); + const Shdr* string_section = sections + elf_header->e_shstrndx; + + const Shdr* section = NULL; + for (int i = 0; i < elf_header->e_shnum; ++i) { + if (sections[i].sh_type == section_type) { + const char* current_section_name = (char*)(elf_base + + string_section->sh_offset + + sections[i].sh_name); + if (!my_strncmp(current_section_name, section_name, name_len)) { + section = §ions[i]; + break; + } + } + } + if (section != NULL && section->sh_size > 0) { + *section_start = elf_base + section->sh_offset; + *section_size = section->sh_size; + } +} + +} // namespace + +bool FindElfSection(const void *elf_mapped_base, + const char *section_name, + uint32_t section_type, + const void **section_start, + int *section_size, + int *elfclass) { + assert(elf_mapped_base); + assert(section_start); + assert(section_size); + + *section_start = NULL; + *section_size = 0; + + const char* elf_base = + static_cast<const char*>(elf_mapped_base); + const ElfW(Ehdr)* elf_header = + reinterpret_cast<const ElfW(Ehdr)*>(elf_base); + if (my_strncmp(elf_base, ELFMAG, SELFMAG) != 0) + return false; + + if (elfclass) { + *elfclass = elf_header->e_ident[EI_CLASS]; + } + + if (elf_header->e_ident[EI_CLASS] == ELFCLASS32) { + FindElfClassSection<ElfClass32>(elf_base, section_name, section_type, + section_start, section_size); + return *section_start != NULL; + } else if (elf_header->e_ident[EI_CLASS] == ELFCLASS64) { + FindElfClassSection<ElfClass64>(elf_base, section_name, section_type, + section_start, section_size); + return *section_start != NULL; + } + + return false; +} + +} // namespace google_breakpad diff --git a/src/common/linux/elfutils.h b/src/common/linux/elfutils.h new file mode 100644 index 00000000..30f2af3f --- /dev/null +++ b/src/common/linux/elfutils.h @@ -0,0 +1,81 @@ +// Copyright (c) 2012, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// elfutils.h: Utilities for dealing with ELF files. +// + +#ifndef COMMON_LINUX_ELFUTILS_H__ +#define COMMON_LINUX_ELFUTILS_H__ + +#if defined(__ANDROID__) +#include <linux/elf.h> +#include "client/linux/android_link.h" +#else +#include <elf.h> +#include <link.h> +#endif +#include <stdint.h> + +namespace google_breakpad { + +// Traits classes so consumers can write templatized code to deal +// with specific ELF bits. +struct ElfClass32 { + typedef Elf32_Addr Addr; + typedef Elf32_Ehdr Ehdr; + typedef Elf32_Nhdr Nhdr; + typedef Elf32_Phdr Phdr; + typedef Elf32_Shdr Shdr; + static const int kClass = ELFCLASS32; +}; + +struct ElfClass64 { + typedef Elf64_Addr Addr; + typedef Elf64_Ehdr Ehdr; + typedef Elf64_Nhdr Nhdr; + typedef Elf64_Phdr Phdr; + typedef Elf64_Shdr Shdr; + static const int kClass = ELFCLASS64; +}; + +// Attempt to find a section named |section_name| of type |section_type| +// in the ELF binary data at |elf_mapped_base|. On success, returns true +// and sets |*section_start| to point to the start of the section data, +// and |*section_size| to the size of the section's data. If |elfclass| +// is not NULL, set |*elfclass| to the ELF file class. +bool FindElfSection(const void *elf_mapped_base, + const char *section_name, + uint32_t section_type, + const void **section_start, + int *section_size, + int *elfclass); + +} // namespace google_breakpad + +#endif // COMMON_LINUX_ELFUTILS_H__ diff --git a/src/common/linux/file_id.cc b/src/common/linux/file_id.cc index ff2f29e2..4e380b06 100644 --- a/src/common/linux/file_id.cc +++ b/src/common/linux/file_id.cc @@ -36,17 +36,11 @@ #include <arpa/inet.h> #include <assert.h> -#if defined(__ANDROID__) -#include <linux/elf.h> -#include "client/linux/android_link.h" -#else -#include <elf.h> -#include <link.h> -#endif #include <string.h> #include <algorithm> +#include "common/linux/elfutils.h" #include "common/linux/linux_libc_support.h" #include "common/linux/memory_mapped_file.h" #include "third_party/lss/linux_syscall_support.h" @@ -61,105 +55,8 @@ FileID::FileID(const char* path) { strncpy(path_, path, sizeof(path_)); } -struct ElfClass32 { - typedef Elf32_Ehdr Ehdr; - typedef Elf32_Nhdr Nhdr; - typedef Elf32_Shdr Shdr; - static const int kClass = ELFCLASS32; -}; - -struct ElfClass64 { - typedef Elf64_Ehdr Ehdr; - typedef Elf64_Nhdr Nhdr; - typedef Elf64_Shdr Shdr; - static const int kClass = ELFCLASS64; -}; - // These six functions are also used inside the crashed process, so be safe // and use the syscall/libc wrappers instead of direct syscalls or libc. -template<typename ElfClass> -static void FindElfClassSection(const char *elf_base, - const char *section_name, - uint32_t section_type, - const void **section_start, - int *section_size) { - typedef typename ElfClass::Ehdr Ehdr; - typedef typename ElfClass::Shdr Shdr; - - assert(elf_base); - assert(section_start); - assert(section_size); - - assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0); - - int name_len = my_strlen(section_name); - - const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base); - assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass); - - const Shdr* sections = - reinterpret_cast<const Shdr*>(elf_base + elf_header->e_shoff); - const Shdr* string_section = sections + elf_header->e_shstrndx; - - const Shdr* section = NULL; - for (int i = 0; i < elf_header->e_shnum; ++i) { - if (sections[i].sh_type == section_type) { - const char* current_section_name = (char*)(elf_base + - string_section->sh_offset + - sections[i].sh_name); - if (!my_strncmp(current_section_name, section_name, name_len)) { - section = §ions[i]; - break; - } - } - } - if (section != NULL && section->sh_size > 0) { - *section_start = elf_base + section->sh_offset; - *section_size = section->sh_size; - } -} - -// Attempt to find a section named |section_name| of type |section_type| -// in the ELF binary data at |elf_mapped_base|. On success, returns true -// and sets |*section_start| to point to the start of the section data, -// and |*section_size| to the size of the section's data. If |elfclass| -// is not NULL, set |*elfclass| to the ELF file class. -static bool FindElfSection(const void *elf_mapped_base, - const char *section_name, - uint32_t section_type, - const void **section_start, - int *section_size, - int *elfclass) { - assert(elf_mapped_base); - assert(section_start); - assert(section_size); - - *section_start = NULL; - *section_size = 0; - - const char* elf_base = - static_cast<const char*>(elf_mapped_base); - const ElfW(Ehdr)* elf_header = - reinterpret_cast<const ElfW(Ehdr)*>(elf_base); - if (my_strncmp(elf_base, ELFMAG, SELFMAG) != 0) - return false; - - if (elfclass) { - *elfclass = elf_header->e_ident[EI_CLASS]; - } - - if (elf_header->e_ident[EI_CLASS] == ELFCLASS32) { - FindElfClassSection<ElfClass32>(elf_base, section_name, section_type, - section_start, section_size); - return *section_start != NULL; - } else if (elf_header->e_ident[EI_CLASS] == ELFCLASS64) { - FindElfClassSection<ElfClass64>(elf_base, section_name, section_type, - section_start, section_size); - return *section_start != NULL; - } - - return false; -} template<typename ElfClass> static bool ElfClassBuildIDNoteIdentifier(const void *section, |