1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 
4 // Copyright (c) 2006, 2012, Google Inc.
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are
9 // met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 
33 // This file is derived from the following files in
34 // toolkit/crashreporter/google-breakpad:
35 //   src/common/android/include/elf.h
36 //   src/common/linux/elfutils.h
37 //   src/common/linux/file_id.h
38 //   src/common/linux/elfutils-inl.h
39 
40 #ifndef LulElfInt_h
41 #define LulElfInt_h
42 
43 // This header defines functions etc internal to the ELF reader.  It
44 // should not be included outside of LulElf.cpp.
45 
46 #include <elf.h>
47 #include <stdlib.h>
48 
49 #include "mozilla/Assertions.h"
50 
51 #include "PlatformMacros.h"
52 
53 // (derived from)
54 // elfutils.h: Utilities for dealing with ELF files.
55 //
56 #include <link.h>
57 
58 #if defined(GP_OS_android)
59 
60 // From toolkit/crashreporter/google-breakpad/src/common/android/include/elf.h
61 // The Android headers don't always define this constant.
62 #  ifndef EM_X86_64
63 #    define EM_X86_64 62
64 #  endif
65 
66 #  ifndef EM_PPC64
67 #    define EM_PPC64 21
68 #  endif
69 
70 #  ifndef EM_S390
71 #    define EM_S390 22
72 #  endif
73 
74 #  ifndef NT_GNU_BUILD_ID
75 #    define NT_GNU_BUILD_ID 3
76 #  endif
77 
78 #  ifndef ElfW
79 #    define ElfW(type) _ElfW(Elf, ELFSIZE, type)
80 #    define _ElfW(e, w, t) _ElfW_1(e, w, _##t)
81 #    define _ElfW_1(e, w, t) e##w##t
82 #  endif
83 
84 #endif
85 
86 #if defined(GP_OS_freebsd)
87 
88 #  ifndef ElfW
89 #    define ElfW(type) Elf_##type
90 #  endif
91 
92 #endif
93 
94 namespace lul {
95 
96 // Traits classes so consumers can write templatized code to deal
97 // with specific ELF bits.
98 struct ElfClass32 {
99   typedef Elf32_Addr Addr;
100   typedef Elf32_Ehdr Ehdr;
101   typedef Elf32_Nhdr Nhdr;
102   typedef Elf32_Phdr Phdr;
103   typedef Elf32_Shdr Shdr;
104   typedef Elf32_Half Half;
105   typedef Elf32_Off Off;
106   typedef Elf32_Word Word;
107   static const int kClass = ELFCLASS32;
108   static const size_t kAddrSize = sizeof(Elf32_Addr);
109 };
110 
111 struct ElfClass64 {
112   typedef Elf64_Addr Addr;
113   typedef Elf64_Ehdr Ehdr;
114   typedef Elf64_Nhdr Nhdr;
115   typedef Elf64_Phdr Phdr;
116   typedef Elf64_Shdr Shdr;
117   typedef Elf64_Half Half;
118   typedef Elf64_Off Off;
119   typedef Elf64_Word Word;
120   static const int kClass = ELFCLASS64;
121   static const size_t kAddrSize = sizeof(Elf64_Addr);
122 };
123 
124 bool IsValidElf(const void* elf_header);
125 int ElfClass(const void* elf_base);
126 
127 // Attempt to find a section named |section_name| of type |section_type|
128 // in the ELF binary data at |elf_mapped_base|. On success, returns true
129 // and sets |*section_start| to point to the start of the section data,
130 // and |*section_size| to the size of the section's data. If |elfclass|
131 // is not NULL, set |*elfclass| to the ELF file class.
132 bool FindElfSection(const void* elf_mapped_base, const char* section_name,
133                     uint32_t section_type, const void** section_start,
134                     int* section_size, int* elfclass);
135 
136 // Internal helper method, exposed for convenience for callers
137 // that already have more info.
138 template <typename ElfClass>
139 const typename ElfClass::Shdr* FindElfSectionByName(
140     const char* name, typename ElfClass::Word section_type,
141     const typename ElfClass::Shdr* sections, const char* section_names,
142     const char* names_end, int nsection);
143 
144 // Attempt to find the first segment of type |segment_type| in the ELF
145 // binary data at |elf_mapped_base|. On success, returns true and sets
146 // |*segment_start| to point to the start of the segment data, and
147 // and |*segment_size| to the size of the segment's data. If |elfclass|
148 // is not NULL, set |*elfclass| to the ELF file class.
149 bool FindElfSegment(const void* elf_mapped_base, uint32_t segment_type,
150                     const void** segment_start, int* segment_size,
151                     int* elfclass);
152 
153 // Convert an offset from an Elf header into a pointer to the mapped
154 // address in the current process. Takes an extra template parameter
155 // to specify the return type to avoid having to dynamic_cast the
156 // result.
157 template <typename ElfClass, typename T>
158 const T* GetOffset(const typename ElfClass::Ehdr* elf_header,
159                    typename ElfClass::Off offset);
160 
161 // (derived from)
162 // file_id.h: Return a unique identifier for a file
163 //
164 
165 static const size_t kMDGUIDSize = sizeof(MDGUID);
166 
167 class FileID {
168  public:
169   // Load the identifier for the elf file mapped into memory at |base| into
170   // |identifier|.  Return false if the identifier could not be created for the
171   // file.
172   static bool ElfFileIdentifierFromMappedFile(const void* base,
173                                               uint8_t identifier[kMDGUIDSize]);
174 
175   // Convert the |identifier| data to a NULL terminated string.  The string will
176   // be formatted as a UUID (e.g., 22F065BB-FC9C-49F7-80FE-26A7CEBD7BCE).
177   // The |buffer| should be at least 37 bytes long to receive all of the data
178   // and termination.  Shorter buffers will contain truncated data.
179   static void ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize],
180                                         char* buffer, int buffer_length);
181 };
182 
183 template <typename ElfClass, typename T>
GetOffset(const typename ElfClass::Ehdr * elf_header,typename ElfClass::Off offset)184 const T* GetOffset(const typename ElfClass::Ehdr* elf_header,
185                    typename ElfClass::Off offset) {
186   return reinterpret_cast<const T*>(reinterpret_cast<uintptr_t>(elf_header) +
187                                     offset);
188 }
189 
190 template <typename ElfClass>
FindElfSectionByName(const char * name,typename ElfClass::Word section_type,const typename ElfClass::Shdr * sections,const char * section_names,const char * names_end,int nsection)191 const typename ElfClass::Shdr* FindElfSectionByName(
192     const char* name, typename ElfClass::Word section_type,
193     const typename ElfClass::Shdr* sections, const char* section_names,
194     const char* names_end, int nsection) {
195   MOZ_ASSERT(name != NULL);
196   MOZ_ASSERT(sections != NULL);
197   MOZ_ASSERT(nsection > 0);
198 
199   int name_len = strlen(name);
200   if (name_len == 0) return NULL;
201 
202   for (int i = 0; i < nsection; ++i) {
203     const char* section_name = section_names + sections[i].sh_name;
204     if (sections[i].sh_type == section_type &&
205         names_end - section_name >= name_len + 1 &&
206         strcmp(name, section_name) == 0) {
207       return sections + i;
208     }
209   }
210   return NULL;
211 }
212 
213 }  // namespace lul
214 
215 // And finally, the external interface, offered to LulMain.cpp
216 #include "LulElfExt.h"
217 
218 #endif  // LulElfInt_h
219