Line data Source code
1 : // Copyright (c) 2010, 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 : // linux_dumper.h: Define the google_breakpad::LinuxDumper class, which
31 : // is a base class for extracting information of a crashed process. It
32 : // was originally a complete implementation using the ptrace API, but
33 : // has been refactored to allow derived implementations supporting both
34 : // ptrace and core dump. A portion of the original implementation is now
35 : // in google_breakpad::LinuxPtraceDumper (see linux_ptrace_dumper.h for
36 : // details).
37 :
38 : #ifndef CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_
39 : #define CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_
40 :
41 : #include <elf.h>
42 : #if defined(__ANDROID__)
43 : #include <link.h>
44 : #endif
45 : #include <linux/limits.h>
46 : #include <stdint.h>
47 : #include <sys/types.h>
48 : #include <sys/user.h>
49 :
50 : #include "linux/dump_writer_common/mapping_info.h"
51 : #include "linux/dump_writer_common/thread_info.h"
52 : #include "common/linux/file_id.h"
53 : #include "common/memory.h"
54 : #include "google_breakpad/common/minidump_format.h"
55 :
56 : namespace google_breakpad {
57 :
58 : // Typedef for our parsing of the auxv variables in /proc/pid/auxv.
59 : #if defined(__i386) || defined(__ARM_EABI__) || \
60 : (defined(__mips__) && _MIPS_SIM == _ABIO32)
61 : typedef Elf32_auxv_t elf_aux_entry;
62 : #elif defined(__x86_64) || defined(__aarch64__) || \
63 : (defined(__mips__) && _MIPS_SIM != _ABIO32)
64 : typedef Elf64_auxv_t elf_aux_entry;
65 : #endif
66 :
67 : typedef __typeof__(((elf_aux_entry*) 0)->a_un.a_val) elf_aux_val_t;
68 :
69 : // When we find the VDSO mapping in the process's address space, this
70 : // is the name we use for it when writing it to the minidump.
71 : // This should always be less than NAME_MAX!
72 : const char kLinuxGateLibraryName[] = "linux-gate.so";
73 :
74 : class LinuxDumper {
75 : public:
76 : // The |root_prefix| is prepended to mapping paths before opening them, which
77 : // is useful if the crash originates from a chroot.
78 : explicit LinuxDumper(pid_t pid, const char* root_prefix = "");
79 :
80 : virtual ~LinuxDumper();
81 :
82 : // Parse the data for |threads| and |mappings|.
83 : virtual bool Init();
84 :
85 : // Take any actions that could not be taken in Init(). LateInit() is
86 : // called after all other caller's initialization is complete, and in
87 : // particular after it has called ThreadsSuspend(), so that ptrace is
88 : // available.
89 : virtual bool LateInit();
90 :
91 : // Return true if the dumper performs a post-mortem dump.
92 : virtual bool IsPostMortem() const = 0;
93 :
94 : // Suspend/resume all threads in the given process.
95 : virtual bool ThreadsSuspend() = 0;
96 : virtual bool ThreadsResume() = 0;
97 :
98 : // Read information about the |index|-th thread of |threads_|.
99 : // Returns true on success. One must have called |ThreadsSuspend| first.
100 : virtual bool GetThreadInfoByIndex(size_t index, ThreadInfo* info) = 0;
101 :
102 : // These are only valid after a call to |Init|.
103 0 : const wasteful_vector<pid_t> &threads() { return threads_; }
104 0 : const wasteful_vector<MappingInfo*> &mappings() { return mappings_; }
105 : const MappingInfo* FindMapping(const void* address) const;
106 0 : const wasteful_vector<elf_aux_val_t>& auxv() { return auxv_; }
107 :
108 : // Find a block of memory to take as the stack given the top of stack pointer.
109 : // stack: (output) the lowest address in the memory area
110 : // stack_len: (output) the length of the memory area
111 : // stack_top: the current top of the stack
112 : bool GetStackInfo(const void** stack, size_t* stack_len, uintptr_t stack_top);
113 :
114 0 : PageAllocator* allocator() { return &allocator_; }
115 :
116 : // Copy content of |length| bytes from a given process |child|,
117 : // starting from |src|, into |dest|. Returns true on success.
118 : virtual bool CopyFromProcess(void* dest, pid_t child, const void* src,
119 : size_t length) = 0;
120 :
121 : // Builds a proc path for a certain pid for a node (/proc/<pid>/<node>).
122 : // |path| is a character array of at least NAME_MAX bytes to return the
123 : // result.|node| is the final node without any slashes. Returns true on
124 : // success.
125 : virtual bool BuildProcPath(char* path, pid_t pid, const char* node) const = 0;
126 :
127 : // Generate a File ID from the .text section of a mapped entry.
128 : // If not a member, mapping_id is ignored. This method can also manipulate the
129 : // |mapping|.name to truncate "(deleted)" from the file name if necessary.
130 : bool ElfFileIdentifierForMapping(const MappingInfo& mapping,
131 : bool member,
132 : unsigned int mapping_id,
133 : wasteful_vector<uint8_t>& identifier);
134 :
135 0 : uintptr_t crash_address() const { return crash_address_; }
136 0 : void set_crash_address(uintptr_t crash_address) {
137 0 : crash_address_ = crash_address;
138 0 : }
139 :
140 0 : int crash_signal() const { return crash_signal_; }
141 0 : void set_crash_signal(int crash_signal) { crash_signal_ = crash_signal; }
142 :
143 0 : pid_t crash_thread() const { return crash_thread_; }
144 0 : void set_crash_thread(pid_t crash_thread) { crash_thread_ = crash_thread; }
145 :
146 : // Concatenates the |root_prefix_| and |mapping| path. Writes into |path| and
147 : // returns true unless the string is too long.
148 : bool GetMappingAbsolutePath(const MappingInfo& mapping,
149 : char path[PATH_MAX]) const;
150 :
151 : // Extracts the effective path and file name of from |mapping|. In most cases
152 : // the effective name/path are just the mapping's path and basename. In some
153 : // other cases, however, a library can be mapped from an archive (e.g., when
154 : // loading .so libs from an apk on Android) and this method is able to
155 : // reconstruct the original file name.
156 : void GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
157 : char* file_path,
158 : size_t file_path_size,
159 : char* file_name,
160 : size_t file_name_size);
161 :
162 : protected:
163 : bool ReadAuxv();
164 :
165 : virtual bool EnumerateMappings();
166 :
167 : virtual bool EnumerateThreads() = 0;
168 :
169 : // For the case where a running program has been deleted, it'll show up in
170 : // /proc/pid/maps as "/path/to/program (deleted)". If this is the case, then
171 : // see if '/path/to/program (deleted)' matches /proc/pid/exe and return
172 : // /proc/pid/exe in |path| so ELF identifier generation works correctly. This
173 : // also checks to see if '/path/to/program (deleted)' exists, so it does not
174 : // get fooled by a poorly named binary.
175 : // For programs that don't end with ' (deleted)', this is a no-op.
176 : // This assumes |path| is a buffer with length NAME_MAX.
177 : // Returns true if |path| is modified.
178 : bool HandleDeletedFileInMapping(char* path) const;
179 :
180 : // ID of the crashed process.
181 : const pid_t pid_;
182 :
183 : // Path of the root directory to which mapping paths are relative.
184 : const char* const root_prefix_;
185 :
186 : // Virtual address at which the process crashed.
187 : uintptr_t crash_address_;
188 :
189 : // Signal that terminated the crashed process.
190 : int crash_signal_;
191 :
192 : // ID of the crashed thread.
193 : pid_t crash_thread_;
194 :
195 : mutable PageAllocator allocator_;
196 :
197 : // IDs of all the threads.
198 : wasteful_vector<pid_t> threads_;
199 :
200 : // Info from /proc/<pid>/maps.
201 : wasteful_vector<MappingInfo*> mappings_;
202 :
203 : // Info from /proc/<pid>/auxv
204 : wasteful_vector<elf_aux_val_t> auxv_;
205 :
206 : #if defined(__ANDROID__)
207 : private:
208 : // Android M and later support packed ELF relocations in shared libraries.
209 : // Packing relocations changes the vaddr of the LOAD segments, such that
210 : // the effective load bias is no longer the same as the start address of
211 : // the memory mapping containing the executable parts of the library. The
212 : // packing is applied to the stripped library run on the target, but not to
213 : // any other library, and in particular not to the library used to generate
214 : // breakpad symbols. As a result, we need to adjust the |start_addr| for
215 : // any mapping that results from a shared library that contains Android
216 : // packed relocations, so that it properly represents the effective library
217 : // load bias. The following functions support this adjustment.
218 :
219 : // Check that a given mapping at |start_addr| is for an ELF shared library.
220 : // If it is, place the ELF header in |ehdr| and return true.
221 : // The first LOAD segment in an ELF shared library has offset zero, so the
222 : // ELF file header is at the start of this map entry, and in already mapped
223 : // memory.
224 : bool GetLoadedElfHeader(uintptr_t start_addr, ElfW(Ehdr)* ehdr);
225 :
226 : // For the ELF file mapped at |start_addr|, iterate ELF program headers to
227 : // find the min vaddr of all program header LOAD segments, the vaddr for
228 : // the DYNAMIC segment, and a count of DYNAMIC entries. Return values in
229 : // |min_vaddr_ptr|, |dyn_vaddr_ptr|, and |dyn_count_ptr|.
230 : // The program header table is also in already mapped memory.
231 : void ParseLoadedElfProgramHeaders(ElfW(Ehdr)* ehdr,
232 : uintptr_t start_addr,
233 : uintptr_t* min_vaddr_ptr,
234 : uintptr_t* dyn_vaddr_ptr,
235 : size_t* dyn_count_ptr);
236 :
237 : // Search the DYNAMIC tags for the ELF file with the given |load_bias|, and
238 : // return true if the tags indicate that the file contains Android packed
239 : // relocations. Dynamic tags are found at |dyn_vaddr| past the |load_bias|.
240 : bool HasAndroidPackedRelocations(uintptr_t load_bias,
241 : uintptr_t dyn_vaddr,
242 : size_t dyn_count);
243 :
244 : // If the ELF file mapped at |start_addr| contained Android packed
245 : // relocations, return the load bias that the system linker (or Chromium
246 : // crazy linker) will have used. If the file did not contain Android
247 : // packed relocations, returns |start_addr|, indicating that no adjustment
248 : // is necessary.
249 : // The effective load bias is |start_addr| adjusted downwards by the
250 : // min vaddr in the library LOAD segments.
251 : uintptr_t GetEffectiveLoadBias(ElfW(Ehdr)* ehdr, uintptr_t start_addr);
252 :
253 : // Called from LateInit(). Iterates |mappings_| and rewrites the |start_addr|
254 : // field of any that represent ELF shared libraries with Android packed
255 : // relocations, so that |start_addr| is the load bias that the system linker
256 : // (or Chromium crazy linker) used. This value matches the addresses produced
257 : // when the non-relocation-packed library is used for breakpad symbol
258 : // generation.
259 : void LatePostprocessMappings();
260 : #endif // __ANDROID__
261 : };
262 :
263 : } // namespace google_breakpad
264 :
265 : #endif // CLIENT_LINUX_HANDLER_LINUX_DUMPER_H_
|