diff options
Diffstat (limited to 'src/common/linux/elf_core_dump.cc')
-rw-r--r-- | src/common/linux/elf_core_dump.cc | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/src/common/linux/elf_core_dump.cc b/src/common/linux/elf_core_dump.cc index 0e7db7b1..f5ee3033 100644 --- a/src/common/linux/elf_core_dump.cc +++ b/src/common/linux/elf_core_dump.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. -// * Neither the name of Google Inc. nor the names of its +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -34,6 +33,7 @@ #include <stddef.h> #include <string.h> +#include <unistd.h> namespace google_breakpad { @@ -95,16 +95,29 @@ size_t ElfCoreDump::Note::AlignedSize(size_t size) { // Implementation of ElfCoreDump. -ElfCoreDump::ElfCoreDump() {} +ElfCoreDump::ElfCoreDump() : proc_mem_fd_(-1) {} ElfCoreDump::ElfCoreDump(const MemoryRange& content) - : content_(content) { + : content_(content), proc_mem_fd_(-1) {} + +ElfCoreDump::~ElfCoreDump() { + if (proc_mem_fd_ != -1) { + close(proc_mem_fd_); + proc_mem_fd_ = -1; + } } void ElfCoreDump::SetContent(const MemoryRange& content) { content_ = content; } +void ElfCoreDump::SetProcMem(int fd) { + if (proc_mem_fd_ != -1) { + close(proc_mem_fd_); + } + proc_mem_fd_ = fd; +} + bool ElfCoreDump::IsValid() const { const Ehdr* header = GetHeader(); return (header && @@ -163,6 +176,16 @@ bool ElfCoreDump::CopyData(void* buffer, Addr virtual_address, size_t length) { } } } + + /* fallback: if available, read from /proc/<pid>/mem */ + if (proc_mem_fd_ != -1) { + off_t offset = virtual_address; + ssize_t r = pread(proc_mem_fd_, buffer, length, offset); + if (r < ssize_t(length)) { + return false; + } + return true; + } return false; } |