aboutsummaryrefslogtreecommitdiff
path: root/src/common/linux/elf_core_dump.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/linux/elf_core_dump.cc')
-rw-r--r--src/common/linux/elf_core_dump.cc33
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;
}