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 #ifndef CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_ 31 #define CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_ 32 33 #include <elf.h> 34 #include <linux/limits.h> 35 #include <stdint.h> 36 #include <sys/types.h> 37 #if !defined(__ANDROID__) 38 #include <sys/user.h> 39 #endif 40 41 #include "common/memory.h" 42 #include "google_breakpad/common/minidump_format.h" 43 44 namespace google_breakpad { 45 46 #if defined(__i386) || defined(__x86_64) 47 typedef typeof(((struct user*) 0)->u_debugreg[0]) debugreg_t; 48 #endif 49 50 // Typedef for our parsing of the auxv variables in /proc/pid/auxv. 51 #if defined(__i386) || defined(__ARM_EABI__) 52 #if !defined(__ANDROID__) 53 typedef Elf32_auxv_t elf_aux_entry; 54 #else 55 // Android is missing this structure definition 56 typedef struct 57 { 58 uint32_t a_type; /* Entry type */ 59 union 60 { 61 uint32_t a_val; /* Integer value */ 62 } a_un; 63 } elf_aux_entry; 64 65 #if !defined(AT_SYSINFO_EHDR) 66 #define AT_SYSINFO_EHDR 33 67 #endif 68 #endif // __ANDROID__ 69 #elif defined(__x86_64__) 70 typedef Elf64_auxv_t elf_aux_entry; 71 #endif 72 // When we find the VDSO mapping in the process's address space, this 73 // is the name we use for it when writing it to the minidump. 74 // This should always be less than NAME_MAX! 75 const char kLinuxGateLibraryName[] = "linux-gate.so"; 76 77 // We produce one of these structures for each thread in the crashed process. 78 struct ThreadInfo { 79 pid_t tgid; // thread group id 80 pid_t ppid; // parent process 81 82 // Even on platforms where the stack grows down, the following will point to 83 // the smallest address in the stack. 84 const void* stack; // pointer to the stack area 85 size_t stack_len; // length of the stack to copy 86 87 88 #if defined(__i386) || defined(__x86_64) 89 user_regs_struct regs; 90 user_fpregs_struct fpregs; 91 static const unsigned kNumDebugRegisters = 8; 92 debugreg_t dregs[8]; 93 #if defined(__i386) 94 user_fpxregs_struct fpxregs; 95 #endif // defined(__i386) 96 97 #elif defined(__ARM_EABI__) 98 // Mimicking how strace does this(see syscall.c, search for GETREGS) 99 #if defined(__ANDROID__) 100 struct pt_regs regs; 101 #else 102 struct user_regs regs; 103 struct user_fpregs fpregs; 104 #endif // __ANDROID__ 105 #endif 106 }; 107 108 // One of these is produced for each mapping in the process (i.e. line in 109 // /proc/$x/maps). 110 struct MappingInfo { 111 uintptr_t start_addr; 112 size_t size; 113 size_t offset; // offset into the backed file. 114 char name[NAME_MAX]; 115 }; 116 117 class LinuxDumper { 118 public: 119 explicit LinuxDumper(pid_t pid); 120 121 // Parse the data for |threads| and |mappings|. 122 bool Init(); 123 124 // Suspend/resume all threads in the given process. 125 bool ThreadsSuspend(); 126 bool ThreadsResume(); 127 128 // Read information about the given thread. Returns true on success. One must 129 // have called |ThreadsSuspend| first. 130 bool ThreadInfoGet(pid_t tid, ThreadInfo* info); 131 132 // These are only valid after a call to |Init|. threads()133 const wasteful_vector<pid_t> &threads() { return threads_; } mappings()134 const wasteful_vector<MappingInfo*> &mappings() { return mappings_; } 135 const MappingInfo* FindMapping(const void* address) const; 136 137 // Find a block of memory to take as the stack given the top of stack pointer. 138 // stack: (output) the lowest address in the memory area 139 // stack_len: (output) the length of the memory area 140 // stack_top: the current top of the stack 141 bool GetStackInfo(const void** stack, size_t* stack_len, uintptr_t stack_top); 142 allocator()143 PageAllocator* allocator() { return &allocator_; } 144 145 // memcpy from a remote process. 146 static void CopyFromProcess(void* dest, pid_t child, const void* src, 147 size_t length); 148 149 // Builds a proc path for a certain pid for a node. path is a 150 // character array that is overwritten, and node is the final node 151 // without any slashes. 152 void BuildProcPath(char* path, pid_t pid, const char* node) const; 153 154 // Generate a File ID from the .text section of a mapped entry. 155 // mapping_id may be -1 if this is not a member of mappings_. 156 bool ElfFileIdentifierForMapping(const MappingInfo& mapping, 157 int mapping_id, 158 uint8_t identifier[sizeof(MDGUID)]); 159 160 // Utility method to find the location of where the kernel has 161 // mapped linux-gate.so in memory(shows up in /proc/pid/maps as 162 // [vdso], but we can't guarantee that it's the only virtual dynamic 163 // shared object. Parsing the auxilary vector for AT_SYSINFO_EHDR 164 // is the safest way to go.) 165 void* FindBeginningOfLinuxGateSharedLibrary(const pid_t pid) const; 166 private: 167 bool EnumerateMappings(wasteful_vector<MappingInfo*>* result) const; 168 bool EnumerateThreads(wasteful_vector<pid_t>* result) const; 169 170 // For the case where a running program has been deleted, it'll show up in 171 // /proc/pid/maps as "/path/to/program (deleted)". If this is the case, then 172 // see if '/path/to/program (deleted)' matches /proc/pid/exe and return 173 // /proc/pid/exe in |path| so ELF identifier generation works correctly. This 174 // also checks to see if '/path/to/program (deleted)' exists, so it does not 175 // get fooled by a poorly named binary. 176 // For programs that don't end with ' (deleted)', this is a no-op. 177 // This assumes |path| is a buffer with length NAME_MAX. 178 // Returns true if |path| is modified. 179 bool HandleDeletedFileInMapping(char* path) const; 180 181 const pid_t pid_; 182 183 mutable PageAllocator allocator_; 184 185 bool threads_suspended_; 186 wasteful_vector<pid_t> threads_; // the ids of all the threads 187 wasteful_vector<MappingInfo*> mappings_; // info from /proc/<pid>/maps 188 }; 189 190 } // namespace google_breakpad 191 192 #endif // CLIENT_LINUX_HANDLER_LINUX_DUMPER_H_ 193