diff options
author | primiano@chromium.org <primiano@chromium.org> | 2014-11-25 10:35:53 +0000 |
---|---|---|
committer | primiano@chromium.org <primiano@chromium.org> | 2014-11-25 10:35:53 +0000 |
commit | be21ad819080f9a723bffc708ff4687473a3e6ad (patch) | |
tree | 2fb8e015a7affe614c4e16a8919add74353be000 | |
parent | Microdump processing implementation (diff) | |
download | breakpad-be21ad819080f9a723bffc708ff4687473a3e6ad.tar.xz |
Fix microdump_writer and add unittest.
This adds some small fixes to the microdump writer and introduces
a unittest.
BUG=chromium:410294
R=mmandlis@chromium.org
Review URL: https://breakpad.appspot.com/2814002
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1404 4c0a9323-5329-0410-9bdc-e9ce6186880e
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | Makefile.in | 45 | ||||
-rw-r--r-- | src/client/linux/microdump_writer/microdump_writer.cc | 30 | ||||
-rw-r--r-- | src/client/linux/microdump_writer/microdump_writer_unittest.cc | 130 |
4 files changed, 190 insertions, 19 deletions
diff --git a/Makefile.am b/Makefile.am index 15c53bf6..b7da8c21 100644 --- a/Makefile.am +++ b/Makefile.am @@ -435,6 +435,10 @@ if ANDROID_HOST src_client_linux_linux_client_unittest_shlib_SOURCES += \ src/common/android/breakpad_getcontext.S endif +if LINUX_HOST +src_client_linux_linux_client_unittest_shlib_SOURCES += \ + src/client/linux/microdump_writer/microdump_writer_unittest.cc +endif src_client_linux_linux_client_unittest_shlib_CPPFLAGS = \ -I$(top_srcdir)/src \ diff --git a/Makefile.in b/Makefile.in index 0305745a..cc0dc035 100644 --- a/Makefile.in +++ b/Makefile.in @@ -198,12 +198,16 @@ check_PROGRAMS = $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \ @DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@am__append_17 = \ @DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@ src/processor/stackwalker_selftest -@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_18 = src/common/android/breakpad_getcontext.S \ -@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ src/common/android/breakpad_getcontext_unittest.cc +@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_18 = \ +@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ src/common/android/breakpad_getcontext.S + @ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_19 = \ -@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ -llog -lm +@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ src/common/android/breakpad_getcontext_unittest.cc @ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_20 = \ +@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ -llog -lm + +@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__append_21 = \ @ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ -llog noinst_PROGRAMS = @@ -582,9 +586,10 @@ am__src_client_linux_linux_client_unittest_shlib_SOURCES_DIST = \ src/processor/logging.cc src/processor/minidump.cc \ src/processor/pathname_stripper.cc \ src/common/android/breakpad_getcontext.S \ + src/client/linux/microdump_writer/microdump_writer_unittest.cc \ src/common/android/breakpad_getcontext_unittest.cc -@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__objects_2 = src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.$(OBJEXT) \ -@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@ src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.$(OBJEXT) +@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__objects_2 = src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.$(OBJEXT) +@ANDROID_HOST_TRUE@@LINUX_HOST_TRUE@am__objects_3 = src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.$(OBJEXT) @LINUX_HOST_TRUE@am_src_client_linux_linux_client_unittest_shlib_OBJECTS = src/client/linux/handler/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.$(OBJEXT) \ @LINUX_HOST_TRUE@ src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-directory_reader_unittest.$(OBJEXT) \ @LINUX_HOST_TRUE@ src/client/linux/minidump_writer/src_client_linux_linux_client_unittest_shlib-cpu_set_unittest.$(OBJEXT) \ @@ -609,7 +614,9 @@ am__src_client_linux_linux_client_unittest_shlib_SOURCES_DIST = \ @LINUX_HOST_TRUE@ src/processor/src_client_linux_linux_client_unittest_shlib-logging.$(OBJEXT) \ @LINUX_HOST_TRUE@ src/processor/src_client_linux_linux_client_unittest_shlib-minidump.$(OBJEXT) \ @LINUX_HOST_TRUE@ src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.$(OBJEXT) \ -@LINUX_HOST_TRUE@ $(am__objects_2) +@LINUX_HOST_TRUE@ $(am__objects_2) \ +@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.$(OBJEXT) \ +@LINUX_HOST_TRUE@ $(am__objects_3) src_client_linux_linux_client_unittest_shlib_OBJECTS = \ $(am_src_client_linux_linux_client_unittest_shlib_OBJECTS) am__DEPENDENCIES_1 = @@ -2092,7 +2099,9 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS) @LINUX_HOST_TRUE@ src/processor/logging.cc \ @LINUX_HOST_TRUE@ src/processor/minidump.cc \ @LINUX_HOST_TRUE@ src/processor/pathname_stripper.cc \ -@LINUX_HOST_TRUE@ $(am__append_18) +@LINUX_HOST_TRUE@ $(am__append_18) \ +@LINUX_HOST_TRUE@ src/client/linux/microdump_writer/microdump_writer_unittest.cc \ +@LINUX_HOST_TRUE@ $(am__append_19) @LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_shlib_CPPFLAGS = \ @LINUX_HOST_TRUE@ -I$(top_srcdir)/src \ @LINUX_HOST_TRUE@ -I$(top_srcdir)/src/testing/include \ @@ -2102,7 +2111,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS) @LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_shlib_LDFLAGS = \ @LINUX_HOST_TRUE@ -shared -Wl,-h,linux_client_unittest_shlib \ -@LINUX_HOST_TRUE@ $(am__append_19) +@LINUX_HOST_TRUE@ $(am__append_20) @LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_shlib_LDADD = \ @LINUX_HOST_TRUE@ src/client/linux/crash_generation/crash_generation_client.o \ @LINUX_HOST_TRUE@ src/client/linux/dump_writer_common/seccomp_unwinder.o \ @@ -2134,7 +2143,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS) @LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_SOURCES = @LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_LDFLAGS = \ -@LINUX_HOST_TRUE@ -Wl,-rpath,'$$ORIGIN' $(am__append_20) +@LINUX_HOST_TRUE@ -Wl,-rpath,'$$ORIGIN' $(am__append_21) @LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_LDADD = \ @LINUX_HOST_TRUE@ src/client/linux/linux_client_unittest_shlib @@ -3529,6 +3538,9 @@ src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.$(O src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext.$(OBJEXT): \ src/common/android/$(am__dirstamp) \ src/common/android/$(DEPDIR)/$(am__dirstamp) +src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.$(OBJEXT): \ + src/client/linux/microdump_writer/$(am__dirstamp) \ + src/client/linux/microdump_writer/$(DEPDIR)/$(am__dirstamp) src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.$(OBJEXT): \ src/common/android/$(am__dirstamp) \ src/common/android/$(DEPDIR)/$(am__dirstamp) @@ -4255,6 +4267,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/handler/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-exception_handler_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/log/$(DEPDIR)/log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/microdump_writer/$(DEPDIR)/microdump_writer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/linux_core_dumper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/linux_dumper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/client/linux/minidump_writer/$(DEPDIR)/linux_ptrace_dumper.Po@am__quote@ @@ -4911,6 +4924,20 @@ src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.obj @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_client_linux_linux_client_unittest_shlib-pathname_stripper.obj `if test -f 'src/processor/pathname_stripper.cc'; then $(CYGPATH_W) 'src/processor/pathname_stripper.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/pathname_stripper.cc'; fi` +src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o: src/client/linux/microdump_writer/microdump_writer_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o -MD -MP -MF src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Tpo -c -o src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o `test -f 'src/client/linux/microdump_writer/microdump_writer_unittest.cc' || echo '$(srcdir)/'`src/client/linux/microdump_writer/microdump_writer_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Tpo src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/microdump_writer/microdump_writer_unittest.cc' object='src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.o `test -f 'src/client/linux/microdump_writer/microdump_writer_unittest.cc' || echo '$(srcdir)/'`src/client/linux/microdump_writer/microdump_writer_unittest.cc + +src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj: src/client/linux/microdump_writer/microdump_writer_unittest.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj -MD -MP -MF src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Tpo -c -o src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj `if test -f 'src/client/linux/microdump_writer/microdump_writer_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/microdump_writer/microdump_writer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/microdump_writer/microdump_writer_unittest.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Tpo src/client/linux/microdump_writer/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/client/linux/microdump_writer/microdump_writer_unittest.cc' object='src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/client/linux/microdump_writer/src_client_linux_linux_client_unittest_shlib-microdump_writer_unittest.obj `if test -f 'src/client/linux/microdump_writer/microdump_writer_unittest.cc'; then $(CYGPATH_W) 'src/client/linux/microdump_writer/microdump_writer_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/client/linux/microdump_writer/microdump_writer_unittest.cc'; fi` + src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.o: src/common/android/breakpad_getcontext_unittest.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_client_linux_linux_client_unittest_shlib_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.o -MD -MP -MF src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Tpo -c -o src/common/android/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.o `test -f 'src/common/android/breakpad_getcontext_unittest.cc' || echo '$(srcdir)/'`src/common/android/breakpad_getcontext_unittest.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Tpo src/common/android/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-breakpad_getcontext_unittest.Po diff --git a/src/client/linux/microdump_writer/microdump_writer.cc b/src/client/linux/microdump_writer/microdump_writer.cc index 494e2a20..195255f7 100644 --- a/src/client/linux/microdump_writer/microdump_writer.cc +++ b/src/client/linux/microdump_writer/microdump_writer.cc @@ -38,9 +38,10 @@ #include "client/linux/dump_writer_common/thread_info.h" #include "client/linux/dump_writer_common/ucontext_reader.h" #include "client/linux/handler/exception_handler.h" +#include "client/linux/log/log.h" #include "client/linux/minidump_writer/linux_ptrace_dumper.h" #include "common/linux/linux_libc_support.h" -#include "client/linux/log/log.h" +#include "common/scoped_ptr.h" namespace { @@ -50,10 +51,13 @@ using google_breakpad::LinuxPtraceDumper; using google_breakpad::MappingInfo; using google_breakpad::MappingList; using google_breakpad::RawContextCPU; +using google_breakpad::scoped_array; using google_breakpad::SeccompUnwinder; using google_breakpad::ThreadInfo; using google_breakpad::UContextReader; +const size_t kLineBufferSize = 2048; + class MicrodumpWriter { public: MicrodumpWriter(const ExceptionHandler::CrashContext* context, @@ -64,7 +68,10 @@ class MicrodumpWriter { float_state_(context ? &context->float_state : NULL), #endif dumper_(dumper), - mapping_list_(mappings) { } + mapping_list_(mappings), + log_line_(new char[kLineBufferSize]) { + log_line_.get()[0] = '\0'; // Clear out the log line buffer. + } ~MicrodumpWriter() { dumper_->ThreadsResume(); } @@ -91,11 +98,14 @@ class MicrodumpWriter { // Writes one line to the system log. void LogLine(const char* msg) { logger::write(msg, my_strlen(msg)); +#if !defined(__ANDROID__) + logger::write("\n", 1); // Android logger appends the \n. Linux's doesn't. +#endif } // Stages the given string in the current line buffer. void LogAppend(const char* str) { - my_strlcat(log_line_, str, sizeof(log_line_)); + my_strlcat(log_line_.get(), str, kLineBufferSize); } // As above (required to take precedence over template specialization below). @@ -125,8 +135,8 @@ class MicrodumpWriter { // Writes out the current line buffer on the system log. void LogCommitLine() { - logger::write(log_line_, my_strlen(log_line_)); - my_strlcpy(log_line_, "", sizeof(log_line_)); + LogLine(log_line_.get()); + my_strlcpy(log_line_.get(), "", kLineBufferSize); } bool DumpOSInformation() { @@ -139,7 +149,6 @@ class MicrodumpWriter { #else const char kOSId[] = "L"; #endif - LogAppend("O "); LogAppend(kOSId); LogAppend(" \""); @@ -162,8 +171,9 @@ class MicrodumpWriter { size_t stack_len; if (!dumper_->GetStackInfo(&stack, &stack_len, stack_pointer)) { - assert(false); - return false; + // The stack pointer might not be available. In this case we don't hard + // fail, just produce a (almost useless) microdump w/o a stack section. + return true; } LogAppend("S 0 "); @@ -296,7 +306,7 @@ class MicrodumpWriter { LogAppend(module_identifier.data4[5]); LogAppend(module_identifier.data4[6]); LogAppend(module_identifier.data4[7]); - LogAppend(" "); + LogAppend("0 "); // Age is always 0 on Linux. LogAppend(file_name); LogCommitLine(); } @@ -334,7 +344,7 @@ class MicrodumpWriter { #endif LinuxDumper* dumper_; const MappingList& mapping_list_; - char log_line_[512]; + scoped_array<char> log_line_; }; } // namespace diff --git a/src/client/linux/microdump_writer/microdump_writer_unittest.cc b/src/client/linux/microdump_writer/microdump_writer_unittest.cc new file mode 100644 index 00000000..27b23a7d --- /dev/null +++ b/src/client/linux/microdump_writer/microdump_writer_unittest.cc @@ -0,0 +1,130 @@ +// Copyright (c) 2014 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// 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 +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <sys/syscall.h> +#include <sys/types.h> +#include <unistd.h> + +#include <string> + +#include "breakpad_googletest_includes.h" +#include "client/linux/handler/exception_handler.h" +#include "client/linux/microdump_writer/microdump_writer.h" +#include "common/linux/eintr_wrapper.h" +#include "common/linux/ignore_ret.h" +#include "common/scoped_ptr.h" +#include "common/tests/auto_tempdir.h" +#include "common/using_std_string.h" + +using namespace google_breakpad; + +// Length of a formatted GUID string = +// sizeof(MDGUID) * 2 + 4 (for dashes) + 1 (null terminator) +const int kGUIDStringSize = 37; + +namespace { + +typedef testing::Test MicrodumpWriterTest; + +TEST(MicrodumpWriterTest, Setup) { + int fds[2]; + ASSERT_NE(-1, pipe(fds)); + + AutoTempDir temp_dir; + string stderr_file = temp_dir.path() + "/stderr.log"; + int err_fd = open(stderr_file.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); + ASSERT_NE(-1, err_fd); + + const pid_t child = fork(); + if (child == 0) { + close(fds[1]); + char b; + IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b)))); + close(fds[0]); + syscall(__NR_exit); + } + close(fds[0]); + + ExceptionHandler::CrashContext context; + memset(&context, 0, sizeof(context)); + + // Set a non-zero tid to avoid tripping asserts. + context.tid = child; + + // Push some extra mapping to check the MappingList logic. + const uint32_t memory_size = sysconf(_SC_PAGESIZE); + const char* kMemoryName = "libfoo.so"; + const uint8_t kModuleGUID[sizeof(MDGUID)] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF + }; + + MappingInfo info; + info.start_addr = memory_size; + info.size = memory_size; + info.offset = 42; + strcpy(info.name, kMemoryName); + + MappingList mappings; + MappingEntry mapping; + mapping.first = info; + 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-----")); + ASSERT_NE(static_cast<char*>(0), strstr( + buf.get(), "M 0000000000001000 000000000000002A 0000000000001000 " + "33221100554477668899AABBCCDDEEFF0 libfoo.so")); + + close(err_fd); + close(fds[1]); +} + +} // namespace |