aboutsummaryrefslogtreecommitdiff
path: root/src/client/linux/microdump_writer
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/linux/microdump_writer')
-rw-r--r--src/client/linux/microdump_writer/microdump_writer.cc56
-rw-r--r--src/client/linux/microdump_writer/microdump_writer.h8
-rw-r--r--src/client/linux/microdump_writer/microdump_writer_unittest.cc81
3 files changed, 104 insertions, 41 deletions
diff --git a/src/client/linux/microdump_writer/microdump_writer.cc b/src/client/linux/microdump_writer/microdump_writer.cc
index e14f9754..f45925fe 100644
--- a/src/client/linux/microdump_writer/microdump_writer.cc
+++ b/src/client/linux/microdump_writer/microdump_writer.cc
@@ -60,6 +60,8 @@ class MicrodumpWriter {
public:
MicrodumpWriter(const ExceptionHandler::CrashContext* context,
const MappingList& mappings,
+ const char* build_fingerprint,
+ const char* product_info,
LinuxDumper* dumper)
: ucontext_(context ? &context->context : NULL),
#if !defined(__ARM_EABI__) && !defined(__mips__)
@@ -67,6 +69,8 @@ class MicrodumpWriter {
#endif
dumper_(dumper),
mapping_list_(mappings),
+ build_fingerprint_(build_fingerprint),
+ product_info_(product_info),
log_line_(NULL) {
log_line_ = reinterpret_cast<char*>(Alloc(kLineBufferSize));
if (log_line_)
@@ -88,9 +92,9 @@ class MicrodumpWriter {
bool Dump() {
bool success;
LogLine("-----BEGIN BREAKPAD MICRODUMP-----");
- success = DumpOSInformation();
- if (success)
- success = DumpCrashingThread();
+ DumpProductInformation();
+ DumpOSInformation();
+ success = DumpCrashingThread();
if (success)
success = DumpMappings();
LogLine("-----END BREAKPAD MICRODUMP-----");
@@ -143,10 +147,17 @@ class MicrodumpWriter {
my_strlcpy(log_line_, "", kLineBufferSize);
}
- bool DumpOSInformation() {
- struct utsname uts;
- if (uname(&uts))
- return false;
+ void DumpProductInformation() {
+ LogAppend("V ");
+ if (product_info_) {
+ LogAppend(product_info_);
+ } else {
+ LogAppend("UNKNOWN:0.0.0.0");
+ }
+ LogCommitLine();
+ }
+
+ void DumpOSInformation() {
const uint8_t n_cpus = static_cast<uint8_t>(sysconf(_SC_NPROCESSORS_CONF));
#if defined(__ANDROID__)
@@ -178,13 +189,23 @@ class MicrodumpWriter {
LogAppend(" ");
LogAppend(n_cpus);
LogAppend(" ");
- LogAppend(uts.machine);
- LogAppend(" ");
- LogAppend(uts.release);
- LogAppend(" ");
- LogAppend(uts.version);
+ // If the client has attached a build fingerprint to the MinidumpDescriptor
+ // use that one. Otherwise try to get some basic info from uname().
+ if (build_fingerprint_) {
+ LogAppend(build_fingerprint_);
+ } else {
+ struct utsname uts;
+ if (uname(&uts) == 0) {
+ LogAppend(uts.machine);
+ LogAppend(" ");
+ LogAppend(uts.release);
+ LogAppend(" ");
+ LogAppend(uts.version);
+ } else {
+ LogAppend("no build fingerprint available");
+ }
+ }
LogCommitLine();
- return true;
}
bool DumpThreadStack(uint32_t thread_id,
@@ -367,6 +388,8 @@ class MicrodumpWriter {
#endif
LinuxDumper* dumper_;
const MappingList& mapping_list_;
+ const char* const build_fingerprint_;
+ const char* const product_info_;
char* log_line_;
};
} // namespace
@@ -376,7 +399,9 @@ namespace google_breakpad {
bool WriteMicrodump(pid_t crashing_process,
const void* blob,
size_t blob_size,
- const MappingList& mappings) {
+ const MappingList& mappings,
+ const char* build_fingerprint,
+ const char* product_info) {
LinuxPtraceDumper dumper(crashing_process);
const ExceptionHandler::CrashContext* context = NULL;
if (blob) {
@@ -388,7 +413,8 @@ bool WriteMicrodump(pid_t crashing_process,
dumper.set_crash_signal(context->siginfo.si_signo);
dumper.set_crash_thread(context->tid);
}
- MicrodumpWriter writer(context, mappings, &dumper);
+ MicrodumpWriter writer(context, mappings, build_fingerprint, product_info,
+ &dumper);
if (!writer.Init())
return false;
return writer.Dump();
diff --git a/src/client/linux/microdump_writer/microdump_writer.h b/src/client/linux/microdump_writer/microdump_writer.h
index 3c19f3d0..e2185583 100644
--- a/src/client/linux/microdump_writer/microdump_writer.h
+++ b/src/client/linux/microdump_writer/microdump_writer.h
@@ -46,12 +46,18 @@ namespace google_breakpad {
// blob: a blob of data from the crashing process. See exception_handler.h
// blob_size: the length of |blob| in bytes.
// mappings: a list of additional mappings provided by the application.
+// build_fingerprint: a (optional) C string which determines the OS
+// build fingerprint (e.g., aosp/occam/mako:5.1.1/LMY47W/1234:eng/dev-keys).
+// product_info: a (optional) C string which determines the product name and
+// version (e.g., WebView:42.0.2311.136).
//
// Returns true iff successful.
bool WriteMicrodump(pid_t crashing_process,
const void* blob,
size_t blob_size,
- const MappingList& mappings);
+ const MappingList& mappings,
+ const char* build_fingerprint,
+ const char* product_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 52b1d9a9..1fa6f1ff 100644
--- a/src/client/linux/microdump_writer/microdump_writer_unittest.cc
+++ b/src/client/linux/microdump_writer/microdump_writer_unittest.cc
@@ -48,7 +48,11 @@ namespace {
typedef testing::Test MicrodumpWriterTest;
-TEST(MicrodumpWriterTest, Setup) {
+void CrashAndGetMicrodump(
+ const MappingList& mappings,
+ const char* build_fingerprint,
+ const char* product_info,
+ scoped_array<char>* buf) {
int fds[2];
ASSERT_NE(-1, pipe(fds));
@@ -73,6 +77,36 @@ TEST(MicrodumpWriterTest, Setup) {
// Set a non-zero tid to avoid tripping asserts.
context.tid = child;
+ // Redirect temporarily stderr to the stderr.log file.
+ int save_err = dup(STDERR_FILENO);
+ ASSERT_NE(-1, save_err);
+ ASSERT_NE(-1, dup2(err_fd, STDERR_FILENO));
+
+ ASSERT_TRUE(WriteMicrodump(child, &context, sizeof(context), mappings,
+ build_fingerprint, product_info));
+
+ // Revert stderr back to the console.
+ dup2(save_err, STDERR_FILENO);
+ close(save_err);
+
+ // Read back the stderr file and check for the microdump marker.
+ fsync(err_fd);
+ lseek(err_fd, 0, SEEK_SET);
+ const size_t kBufSize = 64 * 1024;
+ buf->reset(new char[kBufSize]);
+ ASSERT_GT(read(err_fd, buf->get(), kBufSize), 0);
+
+ close(err_fd);
+ close(fds[1]);
+
+ ASSERT_NE(static_cast<char*>(0), strstr(
+ buf->get(), "-----BEGIN BREAKPAD MICRODUMP-----"));
+ ASSERT_NE(static_cast<char*>(0), strstr(
+ buf->get(), "-----END BREAKPAD MICRODUMP-----"));
+
+}
+
+TEST(MicrodumpWriterTest, BasicWithMappings) {
// Push some extra mapping to check the MappingList logic.
const uint32_t memory_size = sysconf(_SC_PAGESIZE);
const char* kMemoryName = "libfoo.so";
@@ -93,28 +127,8 @@ TEST(MicrodumpWriterTest, Setup) {
memcpy(mapping.second, kModuleGUID, sizeof(MDGUID));
mappings.push_back(mapping);
- // Redirect temporarily stderr to the stderr.log file.
- int save_err = dup(STDERR_FILENO);
- ASSERT_NE(-1, save_err);
- ASSERT_NE(-1, dup2(err_fd, STDERR_FILENO));
-
- ASSERT_TRUE(WriteMicrodump(child, &context, sizeof(context), mappings));
-
- // Revert stderr back to the console.
- dup2(save_err, STDERR_FILENO);
- close(save_err);
-
- // Read back the stderr file and check for the microdump marker.
- fsync(err_fd);
- lseek(err_fd, 0, SEEK_SET);
- const size_t kBufSize = 64 * 1024;
- scoped_array<char> buf(new char[kBufSize]);
- ASSERT_GT(read(err_fd, buf.get(), kBufSize), 0);
-
- ASSERT_NE(static_cast<char*>(0), strstr(
- buf.get(), "-----BEGIN BREAKPAD MICRODUMP-----"));
- ASSERT_NE(static_cast<char*>(0), strstr(
- buf.get(), "-----END BREAKPAD MICRODUMP-----"));
+ scoped_array<char> buf;
+ CrashAndGetMicrodump(mappings, NULL, NULL, &buf);
#ifdef __LP64__
ASSERT_NE(static_cast<char*>(0), strstr(
@@ -126,8 +140,25 @@ TEST(MicrodumpWriterTest, Setup) {
"33221100554477668899AABBCCDDEEFF0 libfoo.so"));
#endif
- close(err_fd);
- close(fds[1]);
+ // In absence of a product info in the minidump, the writer should just write
+ // an unknown marker.
+ ASSERT_NE(static_cast<char*>(0), strstr(
+ buf.get(), "V UNKNOWN:0.0.0.0"));
+}
+
+// Ensure that the product info and build fingerprint metadata show up in the
+// final microdump if present.
+TEST(MicrodumpWriterTest, BuildFingerprintAndProductInfo) {
+ const char kProductInfo[] = "MockProduct:42.0.2311.99";
+ const char kBuildFingerprint[] =
+ "aosp/occam/mako:5.1.1/LMY47W/12345678:userdegbug/dev-keys";
+ scoped_array<char> buf;
+ MappingList no_mappings;
+
+ CrashAndGetMicrodump(no_mappings, kBuildFingerprint, kProductInfo, &buf);
+
+ ASSERT_NE(static_cast<char*>(0), strstr(buf.get(), kBuildFingerprint));
+ ASSERT_NE(static_cast<char*>(0), strstr(buf.get(), kProductInfo));
}
} // namespace