linux_dumper.h revision b0baafc4da1f3ffb84e267dd19d176db3de1c14e
1b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// Copyright (c) 2009, Google Inc. 2b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// All rights reserved. 3b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// 4b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// Redistribution and use in source and binary forms, with or without 5b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// modification, are permitted provided that the following conditions are 6b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// met: 7b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// 8b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// * Redistributions of source code must retain the above copyright 9b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// notice, this list of conditions and the following disclaimer. 10b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// * Redistributions in binary form must reproduce the above 11b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// copyright notice, this list of conditions and the following disclaimer 12b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// in the documentation and/or other materials provided with the 13b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// distribution. 14b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// * Neither the name of Google Inc. nor the names of its 15b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// contributors may be used to endorse or promote products derived from 16b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// this software without specific prior written permission. 17b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// 18b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 30b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid#ifndef CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_ 31b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid#define CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_ 32b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 33b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid#include <elf.h> 34b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid#include <stdint.h> 35b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid#include <sys/user.h> 36b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid#include <linux/limits.h> 37b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 38b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid#include "common/linux/memory.h" 39b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 40b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsidnamespace google_breakpad { 41b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 42b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsidtypedef typeof(((struct user*) 0)->u_debugreg[0]) debugreg_t; 43b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 44b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// Typedef for our parsing of the auxv variables in /proc/pid/auxv. 45b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid#if defined(__i386) 46b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsidtypedef Elf32_auxv_t elf_aux_entry; 47b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid#elif defined(__x86_64__) 48b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsidtypedef Elf64_auxv_t elf_aux_entry; 49b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid#endif 50b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// When we find the VDSO mapping in the process's address space, this 51b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// is the name we use for it when writing it to the minidump. 52b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// This should always be less than NAME_MAX! 53b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsidconst char kLinuxGateLibraryName[] = "linux-gate.so"; 54b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 55b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// We produce one of these structures for each thread in the crashed process. 56b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsidstruct ThreadInfo { 57b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid pid_t tgid; // thread group id 58b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid pid_t ppid; // parent process 59b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 60b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // Even on platforms where the stack grows down, the following will point to 61b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // the smallest address in the stack. 62b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid const void* stack; // pointer to the stack area 63b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid size_t stack_len; // length of the stack to copy 64b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 65b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid user_regs_struct regs; 66b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid user_fpregs_struct fpregs; 67b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid#if defined(__i386) || defined(__x86_64) 68b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid user_fpxregs_struct fpxregs; 69b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 70b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid static const unsigned kNumDebugRegisters = 8; 71b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid debugreg_t dregs[8]; 72b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid#endif 73b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid}; 74b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 75b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// One of these is produced for each mapping in the process (i.e. line in 76b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid// /proc/$x/maps). 77b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsidstruct MappingInfo { 78b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid uintptr_t start_addr; 79b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid size_t size; 80b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid size_t offset; // offset into the backed file. 81b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid char name[NAME_MAX]; 82b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid}; 83b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 84b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsidclass LinuxDumper { 85b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid public: 86b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid explicit LinuxDumper(pid_t pid); 87b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 88b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // Parse the data for |threads| and |mappings|. 89b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid bool Init(); 90b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 91b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // Suspend/resume all threads in the given process. 92b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid bool ThreadsSuspend(); 93b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid bool ThreadsResume(); 94b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 95b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // Read information about the given thread. Returns true on success. One must 96b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // have called |ThreadsSuspend| first. 97b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid bool ThreadInfoGet(pid_t tid, ThreadInfo* info); 98b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 99b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // These are only valid after a call to |Init|. 100b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid const wasteful_vector<pid_t> &threads() { return threads_; } 101b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid const wasteful_vector<MappingInfo*> &mappings() { return mappings_; } 102b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid const MappingInfo* FindMapping(const void* address) const; 103b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 104b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // Find a block of memory to take as the stack given the top of stack pointer. 105b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // stack: (output) the lowest address in the memory area 106b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // stack_len: (output) the length of the memory area 107b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // stack_top: the current top of the stack 108b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid bool GetStackInfo(const void** stack, size_t* stack_len, uintptr_t stack_top); 109b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 110b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid PageAllocator* allocator() { return &allocator_; } 111b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 112b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // memcpy from a remote process. 113b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid static void CopyFromProcess(void* dest, pid_t child, const void* src, 114b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid size_t length); 115b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 116b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // Builds a proc path for a certain pid for a node. path is a 117b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // character array that is overwritten, and node is the final node 118b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // without any slashes. 119b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid void BuildProcPath(char* path, pid_t pid, const char* node) const; 120b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 121b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // Utility method to find the location of where the kernel has 122b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // mapped linux-gate.so in memory(shows up in /proc/pid/maps as 123b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // [vdso], but we can't guarantee that it's the only virtual dynamic 124b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // shared object. Parsing the auxilary vector for AT_SYSINFO_EHDR 125b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid // is the safest way to go.) 126b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid void* FindBeginningOfLinuxGateSharedLibrary(const pid_t pid) const; 127b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid private: 128b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid bool EnumerateMappings(wasteful_vector<MappingInfo*>* result) const; 129b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid bool EnumerateThreads(wasteful_vector<pid_t>* result) const; 130b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 131b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid const pid_t pid_; 132b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 133b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid mutable PageAllocator allocator_; 134b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 135b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid bool threads_suspened_; 136b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid wasteful_vector<pid_t> threads_; // the ids of all the threads 137b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid wasteful_vector<MappingInfo*> mappings_; // info from /proc/<pid>/maps 138b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid}; 139b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 140b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid} // namespace google_breakpad 141b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid 142b0baafc4da1f3ffb84e267dd19d176db3de1c14enealsid#endif // CLIENT_LINUX_HANDLER_LINUX_DUMPER_H_ 143