diff options
Diffstat (limited to 'src/client/linux/minidump_writer')
-rw-r--r-- | src/client/linux/minidump_writer/linux_core_dumper_unittest.cc | 2 | ||||
-rw-r--r-- | src/client/linux/minidump_writer/linux_dumper.cc | 40 | ||||
-rw-r--r-- | src/client/linux/minidump_writer/linux_dumper.h | 18 |
3 files changed, 59 insertions, 1 deletions
diff --git a/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc b/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc index ae0c965b..f5b299f8 100644 --- a/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc +++ b/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc @@ -41,7 +41,7 @@ using namespace google_breakpad; TEST(LinuxCoreDumperTest, GetMappingAbsolutePath) { const LinuxCoreDumper dumper(getpid(), "core", "/tmp", "/mnt/root"); - const MappingInfo mapping = { 0, 0, 0, false, "/usr/lib/libc.so" }; + const MappingInfo mapping = {0, 0, {0, 0}, 0, false, "/usr/lib/libc.so"}; char path[PATH_MAX]; dumper.GetMappingAbsolutePath(mapping, path); diff --git a/src/client/linux/minidump_writer/linux_dumper.cc b/src/client/linux/minidump_writer/linux_dumper.cc index a95ec7ec..4a15f0cc 100644 --- a/src/client/linux/minidump_writer/linux_dumper.cc +++ b/src/client/linux/minidump_writer/linux_dumper.cc @@ -530,6 +530,8 @@ bool LinuxDumper::EnumerateMappings() { } MappingInfo* const module = new(allocator_) MappingInfo; my_memset(module, 0, sizeof(MappingInfo)); + module->system_mapping_info.start_addr = start_addr; + module->system_mapping_info.end_addr = end_addr; module->start_addr = start_addr; module->size = end_addr - start_addr; module->offset = offset; @@ -703,6 +705,31 @@ bool LinuxDumper::GetStackInfo(const void** stack, size_t* stack_len, return true; } +bool LinuxDumper::StackHasPointerToMapping(const uint8_t* stack_copy, + size_t stack_len, + uintptr_t sp_offset, + const MappingInfo& mapping) { + // Loop over all stack words that would have been on the stack in + // the target process (i.e. are word aligned, and at addresses >= + // the stack pointer). Regardless of the alignment of |stack_copy|, + // the memory starting at |stack_copy| + |offset| represents an + // aligned word in the target process. + const uintptr_t low_addr = mapping.system_mapping_info.start_addr; + const uintptr_t high_addr = mapping.system_mapping_info.end_addr; + const uintptr_t offset = + (sp_offset + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1); + + for (const uint8_t* sp = stack_copy + offset; + sp <= stack_copy + stack_len - sizeof(uintptr_t); + sp += sizeof(uintptr_t)) { + uintptr_t addr; + my_memcpy(&addr, sp, sizeof(uintptr_t)); + if (low_addr <= addr && addr <= high_addr) + return true; + } + return false; +} + // Find the mapping which the given memory address falls in. const MappingInfo* LinuxDumper::FindMapping(const void* address) const { const uintptr_t addr = (uintptr_t) address; @@ -716,6 +743,19 @@ const MappingInfo* LinuxDumper::FindMapping(const void* address) const { return NULL; } +// Find the mapping which the given memory address falls in. Uses the +// unadjusted mapping address range from the kernel, rather than the +// biased range. +const MappingInfo* LinuxDumper::FindMappingNoBias(uintptr_t address) const { + for (size_t i = 0; i < mappings_.size(); ++i) { + if (address >= mappings_[i]->system_mapping_info.start_addr && + address < mappings_[i]->system_mapping_info.end_addr) { + return mappings_[i]; + } + } + return NULL; +} + bool LinuxDumper::HandleDeletedFileInMapping(char* path) const { static const size_t kDeletedSuffixLen = sizeof(kDeletedSuffix) - 1; diff --git a/src/client/linux/minidump_writer/linux_dumper.h b/src/client/linux/minidump_writer/linux_dumper.h index c3c79926..0e20209b 100644 --- a/src/client/linux/minidump_writer/linux_dumper.h +++ b/src/client/linux/minidump_writer/linux_dumper.h @@ -103,6 +103,11 @@ class LinuxDumper { const wasteful_vector<pid_t> &threads() { return threads_; } const wasteful_vector<MappingInfo*> &mappings() { return mappings_; } const MappingInfo* FindMapping(const void* address) const; + // Find the mapping which the given memory address falls in. Unlike + // FindMapping, this method uses the unadjusted mapping address + // ranges from the kernel, rather than the ranges that have had the + // load bias applied. + const MappingInfo* FindMappingNoBias(uintptr_t address) const; const wasteful_vector<elf_aux_val_t>& auxv() { return auxv_; } // Find a block of memory to take as the stack given the top of stack pointer. @@ -111,6 +116,19 @@ class LinuxDumper { // stack_top: the current top of the stack bool GetStackInfo(const void** stack, size_t* stack_len, uintptr_t stack_top); + // Test whether |stack_copy| contains a pointer-aligned word that + // could be an address within a given mapping. + // stack_copy: a copy of the stack to check. |stack_copy| might + // not be word aligned, but it represents word aligned + // data copied from another location. + // stack_len: the length of the allocation pointed to by |stack_copy|. + // sp_offset: the offset relative to stack_copy that reflects the + // current value of the stack pointer. + // mapping: the mapping against which to test stack words. + bool StackHasPointerToMapping(const uint8_t* stack_copy, size_t stack_len, + uintptr_t sp_offset, + const MappingInfo& mapping); + PageAllocator* allocator() { return &allocator_; } // Copy content of |length| bytes from a given process |child|, |