diff options
author | ted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2010-09-17 13:36:11 +0000 |
---|---|---|
committer | ted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2010-09-17 13:36:11 +0000 |
commit | efa30c13f2e0bf2cb60a9d00010e8cdc162c872a (patch) | |
tree | 26d531db43b33b95dcf7da5a0277e658f6ae2f45 /src/client/linux/minidump_writer | |
parent | Fix ./configure --enable-m32 (diff) | |
download | breakpad-efa30c13f2e0bf2cb60a9d00010e8cdc162c872a.tar.xz |
Write a window of memory around the instruction pointer from the crashing thread to the minidump on Linux.
R=nealsid at http://breakpad.appspot.com/194001/show
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@693 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/client/linux/minidump_writer')
-rw-r--r-- | src/client/linux/minidump_writer/minidump_writer.cc | 93 |
1 files changed, 91 insertions, 2 deletions
diff --git a/src/client/linux/minidump_writer/minidump_writer.cc b/src/client/linux/minidump_writer/minidump_writer.cc index 260ce934..6b55ade0 100644 --- a/src/client/linux/minidump_writer/minidump_writer.cc +++ b/src/client/linux/minidump_writer/minidump_writer.cc @@ -46,6 +46,8 @@ #include "client/linux/minidump_writer/minidump_writer.h" #include "client/minidump_file_writer-inl.h" +#include <algorithm> + #include <errno.h> #include <fcntl.h> #include <link.h> @@ -367,7 +369,8 @@ class MinidumpWriter { float_state_(NULL), #endif crashing_tid_(context->tid), - dumper_(crashing_pid) { + dumper_(crashing_pid), + memory_blocks_(dumper_.allocator()) { } bool Init() { @@ -400,7 +403,9 @@ class MinidumpWriter { // A minidump file contains a number of tagged streams. This is the number // of stream which we write. - const unsigned kNumWriters = 11 + !!r_debug; + unsigned kNumWriters = 12; + if (r_debug) + ++kNumWriters; TypedMDRVA<MDRawHeader> header(&minidump_writer_); TypedMDRVA<MDRawDirectory> dir(&minidump_writer_); @@ -427,6 +432,10 @@ class MinidumpWriter { return false; dir.CopyIndex(dir_index++, &dirent); + if (!WriteMemoryListStream(&dirent)) + return false; + dir.CopyIndex(dir_index++, &dirent); + if (!WriteExceptionStream(&dirent)) return false; dir.CopyIndex(dir_index++, &dirent); @@ -635,6 +644,50 @@ class MinidumpWriter { memory.Copy(stack_copy, stack_len); thread.stack.start_of_memory_range = (uintptr_t) (stack); thread.stack.memory = memory.location(); + memory_blocks_.push_back(thread.stack); + + // Copy 256 bytes around crashing instruction pointer to minidump. + const size_t kIPMemorySize = 256; + u_int64_t ip = GetInstructionPointer(); + // Bound it to the upper and lower bounds of the memory map + // it's contained within. If it's not in mapped memory, + // don't bother trying to write it. + bool ip_is_mapped = false; + MDMemoryDescriptor ip_memory_d; + for (unsigned i = 0; i < dumper_.mappings().size(); ++i) { + const MappingInfo& mapping = *dumper_.mappings()[i]; + if (ip >= mapping.start_addr && + ip < mapping.start_addr + mapping.size) { + ip_is_mapped = true; + // Try to get 128 bytes before and after the IP, but + // settle for whatever's available. + ip_memory_d.start_of_memory_range = + std::min(mapping.start_addr, + uintptr_t(ip - (kIPMemorySize / 2))); + ip_memory_d.memory.data_size = + std::min(ptrdiff_t(kIPMemorySize), + ptrdiff_t(mapping.start_addr + mapping.size + - ip_memory_d.start_of_memory_range)); + break; + } + } + + if (ip_is_mapped) { + UntypedMDRVA ip_memory(&minidump_writer_); + if (!ip_memory.Allocate(ip_memory_d.memory.data_size)) + return false; + uint8_t* memory_copy = + (uint8_t*) dumper_.allocator()->Alloc(ip_memory_d.memory.data_size); + dumper_.CopyFromProcess( + memory_copy, + thread.thread_id, + reinterpret_cast<void*>(ip_memory_d.start_of_memory_range), + ip_memory_d.memory.data_size); + ip_memory.Copy(memory_copy, ip_memory_d.memory.data_size); + ip_memory_d.memory = ip_memory.location(); + memory_blocks_.push_back(ip_memory_d); + } + TypedMDRVA<RawContextCPU> cpu(&minidump_writer_); if (!cpu.Allocate()) return false; @@ -657,6 +710,8 @@ class MinidumpWriter { memory.Copy(stack_copy, info.stack_len); thread.stack.start_of_memory_range = (uintptr_t)(info.stack); thread.stack.memory = memory.location(); + memory_blocks_.push_back(thread.stack); + TypedMDRVA<RawContextCPU> cpu(&minidump_writer_); if (!cpu.Allocate()) return false; @@ -757,6 +812,24 @@ class MinidumpWriter { return true; } + bool WriteMemoryListStream(MDRawDirectory* dirent) { + TypedMDRVA<uint32_t> list(&minidump_writer_); + if (!list.AllocateObjectAndArray(memory_blocks_.size(), + sizeof(MDMemoryDescriptor))) + return false; + + dirent->stream_type = MD_MEMORY_LIST_STREAM; + dirent->location = list.location(); + + *list.get() = memory_blocks_.size(); + + for (size_t i = 0; i < memory_blocks_.size(); ++i) { + list.CopyIndexAfterObject(i, &memory_blocks_[i], + sizeof(MDMemoryDescriptor)); + } + return true; + } + bool WriteExceptionStream(MDRawDirectory* dirent) { TypedMDRVA<MDRawExceptionStream> exc(&minidump_writer_); if (!exc.Allocate()) @@ -872,14 +945,26 @@ class MinidumpWriter { uintptr_t GetStackPointer() { return ucontext_->uc_mcontext.gregs[REG_ESP]; } + + uintptr_t GetInstructionPointer() { + return ucontext_->uc_mcontext.gregs[REG_EIP]; + } #elif defined(__x86_64) uintptr_t GetStackPointer() { return ucontext_->uc_mcontext.gregs[REG_RSP]; } + + uintptr_t GetInstructionPointer() { + return ucontext_->uc_mcontext.gregs[REG_RIP]; + } #elif defined(__ARM_EABI__) uintptr_t GetStackPointer() { return ucontext_->uc_mcontext.arm_sp; } + + uintptr_t GetInstructionPointer() { + return ucontext_->uc_mcontext.arm_ip; + } #else #error "This code has not been ported to your platform yet." #endif @@ -1129,6 +1214,10 @@ popline: LinuxDumper dumper_; MinidumpFileWriter minidump_writer_; MDLocationDescriptor crashing_thread_context_; + // Blocks of memory written to the dump. These are all currently + // written while writing the thread list stream, but saved here + // so a memory list stream can be written afterwards. + wasteful_vector<MDMemoryDescriptor> memory_blocks_; }; bool WriteMinidump(const char* filename, pid_t crashing_process, |