aboutsummaryrefslogtreecommitdiff
path: root/src/client/linux/microdump_writer
diff options
context:
space:
mode:
authorTobias Sargeant <tobiasjs@google.com>2017-01-18 15:19:51 +0000
committerTobias Sargeant <tobiasjs@chromium.org>2017-01-18 15:41:07 +0000
commit833cadc0a11f0a061cc8057ee56debe89e412973 (patch)
treeeea313877d37bac5564fc4ea2e9bb9bbb8d14e16 /src/client/linux/microdump_writer
parentAdded classes to support reading unloaded module lists in minidumps. (diff)
downloadbreakpad-833cadc0a11f0a061cc8057ee56debe89e412973.tar.xz
Add API to skip dump if crashing thread doesn't reference a given module
This CL makes it possible to skip a dump if the crashing thread doesn't have any pointers to a given module. The concrete use case is WebView where we would like to skip generating microdump output when webview is unreferenced by the stack and thus cannot be responsible for the crash in a way that would be debuggable. The range of interesting addresses is chosen by examining the process mappings to find the one that contains a pointer that is known to be in the right shared object (i.e. an appropriately chosen function pointer) passed from the client. If the extracted stack does not contain a pointer in this range, then we do not generate a microdump. If the stack extraction fails, we still generate a microdump (without a stack). BUG=664460 Change-Id: If19406a13168264f7751245fc39591bd6cdbf5df Reviewed-on: https://chromium-review.googlesource.com/419476 Reviewed-by: Robert Sesek <rsesek@chromium.org> Reviewed-by: Primiano Tucci <primiano@chromium.org>
Diffstat (limited to 'src/client/linux/microdump_writer')
-rw-r--r--src/client/linux/microdump_writer/microdump_writer.cc48
-rw-r--r--src/client/linux/microdump_writer/microdump_writer.h2
-rw-r--r--src/client/linux/microdump_writer/microdump_writer_unittest.cc29
3 files changed, 35 insertions, 44 deletions
diff --git a/src/client/linux/microdump_writer/microdump_writer.cc b/src/client/linux/microdump_writer/microdump_writer.cc
index 6ed69ea9..8109a981 100644
--- a/src/client/linux/microdump_writer/microdump_writer.cc
+++ b/src/client/linux/microdump_writer/microdump_writer.cc
@@ -132,6 +132,8 @@ class MicrodumpWriter {
public:
MicrodumpWriter(const ExceptionHandler::CrashContext* context,
const MappingList& mappings,
+ bool skip_dump_if_principal_mapping_not_referenced,
+ uintptr_t address_within_principal_mapping,
const MicrodumpExtraInfo& microdump_extra_info,
LinuxDumper* dumper)
: ucontext_(context ? &context->context : NULL),
@@ -140,6 +142,9 @@ class MicrodumpWriter {
#endif
dumper_(dumper),
mapping_list_(mappings),
+ skip_dump_if_principal_mapping_not_referenced_(
+ skip_dump_if_principal_mapping_not_referenced),
+ address_within_principal_mapping_(address_within_principal_mapping),
microdump_extra_info_(microdump_extra_info),
log_line_(NULL),
stack_copy_(NULL),
@@ -252,37 +257,22 @@ class MicrodumpWriter {
reinterpret_cast<const void*>(stack_lower_bound_),
stack_len_);
- if (!microdump_extra_info_.suppress_microdump_based_on_interest_range)
- return CAPTURE_OK;
+ if (!skip_dump_if_principal_mapping_not_referenced_) return CAPTURE_OK;
- uintptr_t low_addr = microdump_extra_info_.interest_range_start;
- uintptr_t high_addr = microdump_extra_info_.interest_range_end;
+ const MappingInfo* principal_mapping =
+ dumper_->FindMappingNoBias(address_within_principal_mapping_);
+ if (!principal_mapping) return CAPTURE_UNINTERESTING;
+ uintptr_t low_addr = principal_mapping->start_addr;
+ uintptr_t high_addr = principal_mapping->start_addr + principal_mapping->size;
uintptr_t pc = UContextReader::GetInstructionPointer(ucontext_);
if (low_addr <= pc && pc <= high_addr) return CAPTURE_OK;
- // Loop over all stack words that would have been on the stack in
- // the target process. (i.e. ones that are >= |stack_pointer_| and
- // < |stack_lower_bound_| + |stack_len_| in the target
- // process).
- // |stack_lower_bound_| is page aligned, and thus also pointer
- // aligned. Because the stack pointer might be unaligned, we round
- // the offset down to word alignment. |stack_pointer_| >
- // |stack_lower_bound_|, so this never results in a negative
- // offset.
- // Regardless of the alignment of |stack_copy_|, the memory
- // starting at |stack_copy_| + |offset| represents an aligned word
- // in the target process.
- uintptr_t offset =
- ((stack_pointer_ - stack_lower_bound_) & ~(sizeof(uintptr_t) - 1));
- for (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 CAPTURE_OK;
+ if (dumper_->StackHasPointerToMapping(stack_copy_, stack_len_,
+ stack_pointer_ - stack_lower_bound_,
+ *principal_mapping)) {
+ return CAPTURE_OK;
}
-
return CAPTURE_UNINTERESTING;
}
@@ -588,6 +578,8 @@ class MicrodumpWriter {
#endif
LinuxDumper* dumper_;
const MappingList& mapping_list_;
+ bool skip_dump_if_principal_mapping_not_referenced_;
+ uintptr_t address_within_principal_mapping_;
const MicrodumpExtraInfo microdump_extra_info_;
char* log_line_;
@@ -613,6 +605,8 @@ bool WriteMicrodump(pid_t crashing_process,
const void* blob,
size_t blob_size,
const MappingList& mappings,
+ bool skip_dump_if_principal_mapping_not_referenced,
+ uintptr_t address_within_principal_mapping,
const MicrodumpExtraInfo& microdump_extra_info) {
LinuxPtraceDumper dumper(crashing_process);
const ExceptionHandler::CrashContext* context = NULL;
@@ -625,7 +619,9 @@ bool WriteMicrodump(pid_t crashing_process,
dumper.set_crash_signal(context->siginfo.si_signo);
dumper.set_crash_thread(context->tid);
}
- MicrodumpWriter writer(context, mappings, microdump_extra_info, &dumper);
+ MicrodumpWriter writer(
+ context, mappings, skip_dump_if_principal_mapping_not_referenced,
+ address_within_principal_mapping, microdump_extra_info, &dumper);
if (!writer.Init())
return false;
writer.Dump();
diff --git a/src/client/linux/microdump_writer/microdump_writer.h b/src/client/linux/microdump_writer/microdump_writer.h
index 7c742761..78af86df 100644
--- a/src/client/linux/microdump_writer/microdump_writer.h
+++ b/src/client/linux/microdump_writer/microdump_writer.h
@@ -58,6 +58,8 @@ bool WriteMicrodump(pid_t crashing_process,
const void* blob,
size_t blob_size,
const MappingList& mappings,
+ bool skip_dump_if_main_module_not_referenced,
+ uintptr_t address_within_main_module,
const MicrodumpExtraInfo& microdump_extra_info);
} // namespace google_breakpad
diff --git a/src/client/linux/microdump_writer/microdump_writer_unittest.cc b/src/client/linux/microdump_writer/microdump_writer_unittest.cc
index 42677852..5d028bd3 100644
--- a/src/client/linux/microdump_writer/microdump_writer_unittest.cc
+++ b/src/client/linux/microdump_writer/microdump_writer_unittest.cc
@@ -60,18 +60,11 @@ typedef testing::Test MicrodumpWriterTest;
MicrodumpExtraInfo MakeMicrodumpExtraInfo(
const char* build_fingerprint,
const char* product_info,
- const char* gpu_fingerprint,
- bool suppress_microdump_based_on_interest_range = false,
- uintptr_t interest_range_start = 0,
- uintptr_t interest_range_end = 0) {
+ const char* gpu_fingerprint) {
MicrodumpExtraInfo info;
info.build_fingerprint = build_fingerprint;
info.product_info = product_info;
info.gpu_fingerprint = gpu_fingerprint;
- info.suppress_microdump_based_on_interest_range =
- suppress_microdump_based_on_interest_range;
- info.interest_range_start = interest_range_start;
- info.interest_range_end = interest_range_end;
return info;
}
@@ -82,7 +75,9 @@ bool ContainsMicrodump(const std::string& buf) {
void CrashAndGetMicrodump(const MappingList& mappings,
const MicrodumpExtraInfo& microdump_extra_info,
- std::string* microdump) {
+ std::string* microdump,
+ bool skip_dump_if_principal_mapping_not_referenced = false,
+ uintptr_t address_within_principal_mapping = 0) {
int fds[2];
ASSERT_NE(-1, pipe(fds));
@@ -116,7 +111,8 @@ void CrashAndGetMicrodump(const MappingList& mappings,
ASSERT_NE(-1, dup2(err_fd, STDERR_FILENO));
ASSERT_TRUE(WriteMicrodump(child, &context, sizeof(context), mappings,
- microdump_extra_info));
+ skip_dump_if_principal_mapping_not_referenced,
+ address_within_principal_mapping, microdump_extra_info));
// Revert stderr back to the console.
dup2(save_err, STDERR_FILENO);
@@ -239,13 +235,12 @@ TEST(MicrodumpWriterTest, NoOutputIfUninteresting) {
const char kGPUFingerprint[] =
"Qualcomm;Adreno (TM) 330;OpenGL ES 3.0 V@104.0 AU@ (GIT@Id3510ff6dc)";
const MicrodumpExtraInfo kMicrodumpExtraInfo(
- MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint,
- true, 0xdeadbeef, 0xdeadbeef - 1));
+ MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint));
std::string buf;
MappingList no_mappings;
- CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf);
+ CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf, true, 0);
ASSERT_FALSE(ContainsMicrodump(buf));
}
@@ -259,15 +254,13 @@ TEST(MicrodumpWriterTest, OutputIfInteresting) {
"Qualcomm;Adreno (TM) 330;OpenGL ES 3.0 V@104.0 AU@ (GIT@Id3510ff6dc)";
const MicrodumpExtraInfo kMicrodumpExtraInfo(
- MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint,
- true,
- reinterpret_cast<uintptr_t>(&__executable_start),
- reinterpret_cast<uintptr_t>(&__etext)));
+ MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, kGPUFingerprint));
std::string buf;
MappingList no_mappings;
- CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf);
+ CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfo, &buf, true,
+ reinterpret_cast<uintptr_t>(CrashAndGetMicrodump));
ASSERT_TRUE(ContainsMicrodump(buf));
}