toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2006, 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.
    30 // minidump_file_writer.cc: Minidump file writer implementation.
    31 //
    32 // See minidump_file_writer.h for documentation.
    34 #include <fcntl.h>
    35 #include <limits.h>
    36 #include <stdio.h>
    37 #include <string.h>
    38 #include <unistd.h>
    40 #include "client/minidump_file_writer-inl.h"
    41 #include "common/linux/linux_libc_support.h"
    42 #include "common/string_conversion.h"
    43 #if __linux__
    44 #include "third_party/lss/linux_syscall_support.h"
    45 #endif
    47 namespace google_breakpad {
    49 const MDRVA MinidumpFileWriter::kInvalidMDRVA = static_cast<MDRVA>(-1);
    51 MinidumpFileWriter::MinidumpFileWriter()
    52     : file_(-1),
    53       close_file_when_destroyed_(true),
    54       position_(0),
    55       size_(0) {
    56 }
    58 MinidumpFileWriter::~MinidumpFileWriter() {
    59   if (close_file_when_destroyed_)
    60     Close();
    61 }
    63 bool MinidumpFileWriter::Open(const char *path) {
    64   assert(file_ == -1);
    65 #if __linux__
    66   file_ = sys_open(path, O_WRONLY | O_CREAT | O_EXCL, 0600);
    67 #else
    68   file_ = open(path, O_WRONLY | O_CREAT | O_EXCL, 0600);
    69 #endif
    71   return file_ != -1;
    72 }
    74 void MinidumpFileWriter::SetFile(const int file) {
    75   assert(file_ == -1);
    76   file_ = file;
    77   close_file_when_destroyed_ = false;
    78 }
    80 bool MinidumpFileWriter::Close() {
    81   bool result = true;
    83   if (file_ != -1) {
    84     if (-1 == ftruncate(file_, position_)) {
    85        return false;
    86     }
    87 #if __linux__
    88     result = (sys_close(file_) == 0);
    89 #else
    90     result = (close(file_) == 0);
    91 #endif
    92     file_ = -1;
    93   }
    95   return result;
    96 }
    98 bool MinidumpFileWriter::CopyStringToMDString(const wchar_t *str,
    99                                               unsigned int length,
   100                                               TypedMDRVA<MDString> *mdstring) {
   101   bool result = true;
   102   if (sizeof(wchar_t) == sizeof(uint16_t)) {
   103     // Shortcut if wchar_t is the same size as MDString's buffer
   104     result = mdstring->Copy(str, mdstring->get()->length);
   105   } else {
   106     uint16_t out[2];
   107     int out_idx = 0;
   109     // Copy the string character by character
   110     while (length && result) {
   111       UTF32ToUTF16Char(*str, out);
   112       if (!out[0])
   113         return false;
   115       // Process one character at a time
   116       --length;
   117       ++str;
   119       // Append the one or two UTF-16 characters.  The first one will be non-
   120       // zero, but the second one may be zero, depending on the conversion from
   121       // UTF-32.
   122       int out_count = out[1] ? 2 : 1;
   123       size_t out_size = sizeof(uint16_t) * out_count;
   124       result = mdstring->CopyIndexAfterObject(out_idx, out, out_size);
   125       out_idx += out_count;
   126     }
   127   }
   128   return result;
   129 }
   131 bool MinidumpFileWriter::CopyStringToMDString(const char *str,
   132                                               unsigned int length,
   133                                               TypedMDRVA<MDString> *mdstring) {
   134   bool result = true;
   135   uint16_t out[2];
   136   int out_idx = 0;
   138   // Copy the string character by character
   139   while (length && result) {
   140     int conversion_count = UTF8ToUTF16Char(str, length, out);
   141     if (!conversion_count)
   142       return false;
   144     // Move the pointer along based on the nubmer of converted characters
   145     length -= conversion_count;
   146     str += conversion_count;
   148     // Append the one or two UTF-16 characters
   149     int out_count = out[1] ? 2 : 1;
   150     size_t out_size = sizeof(uint16_t) * out_count;
   151     result = mdstring->CopyIndexAfterObject(out_idx, out, out_size);
   152     out_idx += out_count;
   153   }
   154   return result;
   155 }
   157 template <typename CharType>
   158 bool MinidumpFileWriter::WriteStringCore(const CharType *str,
   159                                          unsigned int length,
   160                                          MDLocationDescriptor *location) {
   161   assert(str);
   162   assert(location);
   163   // Calculate the mdstring length by either limiting to |length| as passed in
   164   // or by finding the location of the NULL character.
   165   unsigned int mdstring_length = 0;
   166   if (!length)
   167     length = INT_MAX;
   168   for (; mdstring_length < length && str[mdstring_length]; ++mdstring_length)
   169     ;
   171   // Allocate the string buffer
   172   TypedMDRVA<MDString> mdstring(this);
   173   if (!mdstring.AllocateObjectAndArray(mdstring_length + 1, sizeof(uint16_t)))
   174     return false;
   176   // Set length excluding the NULL and copy the string
   177   mdstring.get()->length =
   178       static_cast<uint32_t>(mdstring_length * sizeof(uint16_t));
   179   bool result = CopyStringToMDString(str, mdstring_length, &mdstring);
   181   // NULL terminate
   182   if (result) {
   183     uint16_t ch = 0;
   184     result = mdstring.CopyIndexAfterObject(mdstring_length, &ch, sizeof(ch));
   186     if (result)
   187       *location = mdstring.location();
   188   }
   190   return result;
   191 }
   193 bool MinidumpFileWriter::WriteString(const wchar_t *str, unsigned int length,
   194                  MDLocationDescriptor *location) {
   195   return WriteStringCore(str, length, location);
   196 }
   198 bool MinidumpFileWriter::WriteString(const char *str, unsigned int length,
   199                  MDLocationDescriptor *location) {
   200   return WriteStringCore(str, length, location);
   201 }
   203 bool MinidumpFileWriter::WriteMemory(const void *src, size_t size,
   204                                      MDMemoryDescriptor *output) {
   205   assert(src);
   206   assert(output);
   207   UntypedMDRVA mem(this);
   209   if (!mem.Allocate(size))
   210     return false;
   211   if (!mem.Copy(src, mem.size()))
   212     return false;
   214   output->start_of_memory_range = reinterpret_cast<uint64_t>(src);
   215   output->memory = mem.location();
   217   return true;
   218 }
   220 MDRVA MinidumpFileWriter::Allocate(size_t size) {
   221   assert(size);
   222   assert(file_ != -1);
   223   size_t aligned_size = (size + 7) & ~7;  // 64-bit alignment
   225   if (position_ + aligned_size > size_) {
   226     size_t growth = aligned_size;
   227     size_t minimal_growth = getpagesize();
   229     // Ensure that the file grows by at least the size of a memory page
   230     if (growth < minimal_growth)
   231       growth = minimal_growth;
   233     size_t new_size = size_ + growth;
   234     if (ftruncate(file_, new_size) != 0)
   235       return kInvalidMDRVA;
   237     size_ = new_size;
   238   }
   240   MDRVA current_position = position_;
   241   position_ += static_cast<MDRVA>(aligned_size);
   243   return current_position;
   244 }
   246 bool MinidumpFileWriter::Copy(MDRVA position, const void *src, ssize_t size) {
   247   assert(src);
   248   assert(size);
   249   assert(file_ != -1);
   251   // Ensure that the data will fit in the allocated space
   252   if (static_cast<size_t>(size + position) > size_)
   253     return false;
   255   // Seek and write the data
   256 #if __linux__
   257   if (sys_lseek(file_, position, SEEK_SET) == static_cast<off_t>(position)) {
   258     if (sys_write(file_, src, size) == size) {
   259 #else
   260   if (lseek(file_, position, SEEK_SET) == static_cast<off_t>(position)) {
   261     if (write(file_, src, size) == size) {
   262 #endif
   263       return true;
   264     }
   265   }
   267   return false;
   268 }
   270 bool UntypedMDRVA::Allocate(size_t size) {
   271   assert(size_ == 0);
   272   size_ = size;
   273   position_ = writer_->Allocate(size_);
   274   return position_ != MinidumpFileWriter::kInvalidMDRVA;
   275 }
   277 bool UntypedMDRVA::Copy(MDRVA pos, const void *src, size_t size) {
   278   assert(src);
   279   assert(size);
   280   assert(pos + size <= position_ + size_);
   281   return writer_->Copy(pos, src, size);
   282 }
   284 }  // namespace google_breakpad

mercurial