1 // Copyright 2012 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 // 29 // elfutils.h: Utilities for dealing with ELF files. 30 // 31 32 #ifndef COMMON_LINUX_ELFUTILS_H_ 33 #define COMMON_LINUX_ELFUTILS_H_ 34 35 #include <elf.h> 36 #include <link.h> 37 #include <stdint.h> 38 39 #include "common/memory_allocator.h" 40 41 namespace google_breakpad { 42 43 typedef struct Elf32_Chdr { 44 typedef Elf32_Word Type; 45 typedef Elf32_Word Size; 46 typedef Elf32_Addr Addr; 47 48 static_assert(sizeof (Type) == 4); 49 static_assert(sizeof (Size) == 4); 50 static_assert(sizeof (Addr) == 4); 51 52 Type ch_type; // Compression type 53 Size ch_size; // Uncompressed data size in bytes 54 Addr ch_addralign; // Uncompressed data alignment 55 } Elf32_Chdr; 56 57 static_assert(sizeof (Elf32_Chdr) == 12); 58 59 typedef struct Elf64_Chdr { 60 typedef Elf64_Word Type; 61 typedef Elf64_Xword Size; 62 typedef Elf64_Addr Addr; 63 64 static_assert(sizeof (Type) == 4); 65 static_assert(sizeof (Size) == 8); 66 static_assert(sizeof (Addr) == 8); 67 68 Type ch_type; // Compression type 69 Type ch_reserved; // Padding 70 Size ch_size; // Uncompressed data size in bytes 71 Addr ch_addralign; // Uncompressed data alignment 72 } Elf64_Chdr; 73 74 static_assert(sizeof (Elf64_Chdr) == 24); 75 76 // Traits classes so consumers can write templatized code to deal 77 // with specific ELF bits. 78 struct ElfClass32 { 79 typedef Elf32_Addr Addr; 80 typedef Elf32_Dyn Dyn; 81 typedef Elf32_Ehdr Ehdr; 82 typedef Elf32_Nhdr Nhdr; 83 typedef Elf32_Phdr Phdr; 84 typedef Elf32_Shdr Shdr; 85 typedef Elf32_Chdr Chdr; 86 typedef Elf32_Half Half; 87 typedef Elf32_Off Off; 88 typedef Elf32_Sym Sym; 89 typedef Elf32_Word Word; 90 91 static const int kClass = ELFCLASS32; 92 static const uint16_t kMachine = EM_386; 93 static const size_t kAddrSize = sizeof(Elf32_Addr); 94 static constexpr const char* kMachineName = "x86"; 95 }; 96 97 struct ElfClass64 { 98 typedef Elf64_Addr Addr; 99 typedef Elf64_Dyn Dyn; 100 typedef Elf64_Ehdr Ehdr; 101 typedef Elf64_Nhdr Nhdr; 102 typedef Elf64_Phdr Phdr; 103 typedef Elf64_Shdr Shdr; 104 typedef Elf64_Chdr Chdr; 105 typedef Elf64_Half Half; 106 typedef Elf64_Off Off; 107 typedef Elf64_Sym Sym; 108 typedef Elf64_Word Word; 109 110 static const int kClass = ELFCLASS64; 111 static const uint16_t kMachine = EM_X86_64; 112 static const size_t kAddrSize = sizeof(Elf64_Addr); 113 static constexpr const char* kMachineName = "x86_64"; 114 }; 115 116 bool IsValidElf(const void* elf_header); 117 int ElfClass(const void* elf_base); 118 119 // Attempt to find a section named |section_name| of type |section_type| 120 // in the ELF binary data at |elf_mapped_base|. On success, returns true 121 // and sets |*section_start| to point to the start of the section data, 122 // and |*section_size| to the size of the section's data. 123 bool FindElfSection(const void* elf_mapped_base, 124 const char* section_name, 125 uint32_t section_type, 126 const void** section_start, 127 size_t* section_size); 128 129 // Internal helper method, exposed for convenience for callers 130 // that already have more info. 131 template<typename ElfClass> 132 const typename ElfClass::Shdr* 133 FindElfSectionByName(const char* name, 134 typename ElfClass::Word section_type, 135 const typename ElfClass::Shdr* sections, 136 const char* section_names, 137 const char* names_end, 138 int nsection); 139 140 struct ElfSegment { 141 const void* start; 142 size_t size; 143 }; 144 145 // Attempt to find all segments of type |segment_type| in the ELF 146 // binary data at |elf_mapped_base|. On success, returns true and fills 147 // |*segments| with a list of segments of the given type. 148 bool FindElfSegments(const void* elf_mapped_base, 149 uint32_t segment_type, 150 wasteful_vector<ElfSegment>* segments); 151 152 // Convert an offset from an Elf header into a pointer to the mapped 153 // address in the current process. Takes an extra template parameter 154 // to specify the return type to avoid having to dynamic_cast the 155 // result. 156 template<typename ElfClass, typename T> 157 const T* 158 GetOffset(const typename ElfClass::Ehdr* elf_header, 159 typename ElfClass::Off offset); 160 161 // Read the value of DT_SONAME from the elf file mapped at |elf_base|. Returns 162 // true and fills |soname| with the result if found. 163 bool ElfFileSoNameFromMappedFile(const void* elf_base, 164 char* soname, 165 size_t soname_size); 166 167 } // namespace google_breakpad 168 169 #endif // COMMON_LINUX_ELFUTILS_H_ 170