diff --git a/src/client/linux/microdump_writer/microdump_writer.cc b/src/client/linux/microdump_writer/microdump_writer.cc index 065ca0b7..3764eec2 100644 --- a/src/client/linux/microdump_writer/microdump_writer.cc +++ b/src/client/linux/microdump_writer/microdump_writer.cc @@ -483,6 +483,12 @@ class MicrodumpWriter { #if !defined(__LP64__) void DumpFreeSpace() { + const MappingInfo* stack_mapping = nullptr; + ThreadInfo info; + if (dumper_->GetThreadInfoByIndex(dumper_->GetMainThreadIndex(), &info)) { + stack_mapping = dumper_->FindMappingNoBias(info.stack_pointer); + } + const google_breakpad::wasteful_vector& mappings = dumper_->mappings(); if (mappings.size() == 0) return; @@ -515,6 +521,14 @@ class MicrodumpWriter { ++curr; } + if (mappings[curr] == stack_mapping) { + // Because we can't determine the top of userspace mappable + // memory we treat the start of the process stack as the top + // of the allocatable address space. Once we reach + // |stack_mapping| we are done scanning for free space regions. + break; + } + size_t next = NextOrderedMapping(mappings, curr); if (next == std::numeric_limits::max()) break; @@ -602,7 +616,7 @@ class MicrodumpWriter { // crashed process. |stack_lower_bound_| <= |stack_pointer_| uintptr_t stack_lower_bound_; - // The stack pointer in the crashed process. + // The stack pointer of the crashed thread. uintptr_t stack_pointer_; }; } // namespace diff --git a/src/client/linux/minidump_writer/linux_dumper.h b/src/client/linux/minidump_writer/linux_dumper.h index 23c78e08..3a9a2e8b 100644 --- a/src/client/linux/minidump_writer/linux_dumper.h +++ b/src/client/linux/minidump_writer/linux_dumper.h @@ -99,6 +99,13 @@ class LinuxDumper { // Returns true on success. One must have called |ThreadsSuspend| first. virtual bool GetThreadInfoByIndex(size_t index, ThreadInfo* info) = 0; + size_t GetMainThreadIndex() const { + for (size_t i = 0; i < threads_.size(); ++i) { + if (threads_[i] == pid_) return i; + } + return -1u; + } + // These are only valid after a call to |Init|. const wasteful_vector &threads() { return threads_; } const wasteful_vector &mappings() { return mappings_; }