Home | History | Annotate | Download | only in microdump_writer
      1 // Copyright (c) 2014 Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 #include <sys/syscall.h>
     31 #include <sys/types.h>
     32 #include <unistd.h>
     33 
     34 #include <string>
     35 
     36 #include "breakpad_googletest_includes.h"
     37 #include "client/linux/handler/exception_handler.h"
     38 #include "client/linux/microdump_writer/microdump_writer.h"
     39 #include "common/linux/eintr_wrapper.h"
     40 #include "common/linux/ignore_ret.h"
     41 #include "common/scoped_ptr.h"
     42 #include "common/tests/auto_tempdir.h"
     43 #include "common/using_std_string.h"
     44 
     45 using namespace google_breakpad;
     46 
     47 namespace {
     48 
     49 typedef testing::Test MicrodumpWriterTest;
     50 
     51 TEST(MicrodumpWriterTest, Setup) {
     52   int fds[2];
     53   ASSERT_NE(-1, pipe(fds));
     54 
     55   AutoTempDir temp_dir;
     56   string stderr_file = temp_dir.path() + "/stderr.log";
     57   int err_fd = open(stderr_file.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
     58   ASSERT_NE(-1, err_fd);
     59 
     60   const pid_t child = fork();
     61   if (child == 0) {
     62     close(fds[1]);
     63     char b;
     64     IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b))));
     65     close(fds[0]);
     66     syscall(__NR_exit);
     67   }
     68   close(fds[0]);
     69 
     70   ExceptionHandler::CrashContext context;
     71   memset(&context, 0, sizeof(context));
     72 
     73   // Set a non-zero tid to avoid tripping asserts.
     74   context.tid = child;
     75 
     76   // Push some extra mapping to check the MappingList logic.
     77   const uint32_t memory_size = sysconf(_SC_PAGESIZE);
     78   const char* kMemoryName = "libfoo.so";
     79   const uint8_t kModuleGUID[sizeof(MDGUID)] = {
     80      0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
     81      0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
     82   };
     83 
     84   MappingInfo info;
     85   info.start_addr = memory_size;
     86   info.size = memory_size;
     87   info.offset = 42;
     88   strcpy(info.name, kMemoryName);
     89 
     90   MappingList mappings;
     91   MappingEntry mapping;
     92   mapping.first = info;
     93   memcpy(mapping.second, kModuleGUID, sizeof(MDGUID));
     94   mappings.push_back(mapping);
     95 
     96   // Redirect temporarily stderr to the stderr.log file.
     97   int save_err = dup(STDERR_FILENO);
     98   ASSERT_NE(-1, save_err);
     99   ASSERT_NE(-1, dup2(err_fd, STDERR_FILENO));
    100 
    101   ASSERT_TRUE(WriteMicrodump(child, &context, sizeof(context), mappings));
    102 
    103   // Revert stderr back to the console.
    104   dup2(save_err, STDERR_FILENO);
    105   close(save_err);
    106 
    107   // Read back the stderr file and check for the microdump marker.
    108   fsync(err_fd);
    109   lseek(err_fd, 0, SEEK_SET);
    110   const size_t kBufSize = 64 * 1024;
    111   scoped_array<char> buf(new char[kBufSize]);
    112   ASSERT_GT(read(err_fd, buf.get(), kBufSize), 0);
    113 
    114   ASSERT_NE(static_cast<char*>(0), strstr(
    115       buf.get(), "-----BEGIN BREAKPAD MICRODUMP-----"));
    116   ASSERT_NE(static_cast<char*>(0), strstr(
    117       buf.get(), "-----END BREAKPAD MICRODUMP-----"));
    118 
    119 #ifdef __LP64__
    120   ASSERT_NE(static_cast<char*>(0), strstr(
    121       buf.get(), "M 0000000000001000 000000000000002A 0000000000001000 "
    122       "33221100554477668899AABBCCDDEEFF0 libfoo.so"));
    123 #else
    124   ASSERT_NE(static_cast<char*>(0), strstr(
    125       buf.get(), "M 00001000 0000002A 00001000 "
    126       "33221100554477668899AABBCCDDEEFF0 libfoo.so"));
    127 #endif
    128 
    129   close(err_fd);
    130   close(fds[1]);
    131 }
    132 
    133 }  // namespace
    134