Planeshift

minidump_file_writer.h

Go to the documentation of this file.
00001 // Copyright (c) 2006, Google Inc.
00002 // All rights reserved.
00003 //
00004 // Redistribution and use in source and binary forms, with or without
00005 // modification, are permitted provided that the following conditions are
00006 // met:
00007 //
00008 //     * Redistributions of source code must retain the above copyright
00009 // notice, this list of conditions and the following disclaimer.
00010 //     * Redistributions in binary form must reproduce the above
00011 // copyright notice, this list of conditions and the following disclaimer
00012 // in the documentation and/or other materials provided with the
00013 // distribution.
00014 //     * Neither the name of Google Inc. nor the names of its
00015 // contributors may be used to endorse or promote products derived from
00016 // this software without specific prior written permission.
00017 //
00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00021 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00022 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00023 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00024 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00025 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00026 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00028 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 
00030 // minidump_file_writer.h:  Implements file-based minidump generation.  It's
00031 // intended to be used with the Google Breakpad open source crash handling
00032 // project.
00033 
00034 #ifndef CLIENT_MINIDUMP_FILE_WRITER_H__
00035 #define CLIENT_MINIDUMP_FILE_WRITER_H__
00036 
00037 #include <string>
00038 
00039 #include "google_breakpad/common/minidump_format.h"
00040 
00041 namespace google_breakpad {
00042 
00043 class UntypedMDRVA;
00044 template<typename MDType> class TypedMDRVA;
00045 
00046 // The user of this class can Open() a file and add minidump streams, data, and
00047 // strings using the definitions in minidump_format.h.  Since this class is
00048 // expected to be used in a situation where the current process may be
00049 // damaged, it will not allocate heap memory.
00050 // Sample usage:
00051 // MinidumpFileWriter writer;
00052 // writer.Open("/tmp/minidump.dmp");
00053 // TypedMDRVA<MDRawHeader> header(&writer_);
00054 // header.Allocate();
00055 // header->get()->signature = MD_HEADER_SIGNATURE;
00056 //  :
00057 // writer.Close();
00058 //
00059 // An alternative is to use SetFile and provide a file descriptor:
00060 // MinidumpFileWriter writer;
00061 // writer.SetFile(minidump_fd);
00062 // TypedMDRVA<MDRawHeader> header(&writer_);
00063 // header.Allocate();
00064 // header->get()->signature = MD_HEADER_SIGNATURE;
00065 //  :
00066 // writer.Close();
00067 
00068 class MinidumpFileWriter {
00069 public:
00070   // Invalid MDRVA (Minidump Relative Virtual Address)
00071   // returned on failed allocation
00072   static const MDRVA kInvalidMDRVA;
00073 
00074   MinidumpFileWriter();
00075   ~MinidumpFileWriter();
00076 
00077   // Open |path| as the destination of the minidump data.  Any existing file
00078   // will be overwritten.
00079   // Return true on success, or false on failure.
00080   bool Open(const char *path);
00081 
00082   // Sets the file descriptor |file| as the destination of the minidump data.
00083   // Can be used as an alternative to Open() when a file descriptor is
00084   // available.
00085   // Note that |fd| is not closed when the instance of MinidumpFileWriter is
00086   // destroyed.
00087   void SetFile(const int file);
00088 
00089   // Close the current file (that was either created when Open was called, or
00090   // specified with SetFile).
00091   // Return true on success, or false on failure.
00092   bool Close();
00093 
00094   // Copy the contents of |str| to a MDString and write it to the file.
00095   // |str| is expected to be either UTF-16 or UTF-32 depending on the size
00096   // of wchar_t.
00097   // Maximum |length| of characters to copy from |str|, or specify 0 to use the
00098   // entire NULL terminated string.  Copying will stop at the first NULL.
00099   // |location| the allocated location
00100   // Return true on success, or false on failure
00101   bool WriteString(const wchar_t *str, unsigned int length,
00102                    MDLocationDescriptor *location);
00103 
00104   // Same as above, except with |str| as a UTF-8 string
00105   bool WriteString(const char *str, unsigned int length,
00106                    MDLocationDescriptor *location);
00107 
00108   // Write |size| bytes starting at |src| into the current position.
00109   // Return true on success and set |output| to position, or false on failure
00110   bool WriteMemory(const void *src, size_t size, MDMemoryDescriptor *output);
00111 
00112   // Copies |size| bytes from |src| to |position|
00113   // Return true on success, or false on failure
00114   bool Copy(MDRVA position, const void *src, ssize_t size);
00115 
00116   // Return the current position for writing to the minidump
00117   inline MDRVA position() const { return position_; }
00118 
00119  private:
00120   friend class UntypedMDRVA;
00121 
00122   // Allocates an area of |size| bytes.
00123   // Returns the position of the allocation, or kInvalidMDRVA if it was
00124   // unable to allocate the bytes.
00125   MDRVA Allocate(size_t size);
00126 
00127   // The file descriptor for the output file.
00128   int file_;
00129 
00130   // Whether |file_| should be closed when the instance is destroyed.
00131   bool close_file_when_destroyed_;
00132 
00133   // Current position in buffer
00134   MDRVA position_;
00135 
00136   // Current allocated size
00137   size_t size_;
00138 
00139   // Copy |length| characters from |str| to |mdstring|.  These are distinct
00140   // because the underlying MDString is a UTF-16 based string.  The wchar_t
00141   // variant may need to create a MDString that has more characters than the
00142   // source |str|, whereas the UTF-8 variant may coalesce characters to form
00143   // a single UTF-16 character.
00144   bool CopyStringToMDString(const wchar_t *str, unsigned int length,
00145                             TypedMDRVA<MDString> *mdstring);
00146   bool CopyStringToMDString(const char *str, unsigned int length,
00147                             TypedMDRVA<MDString> *mdstring);
00148 
00149   // The common templated code for writing a string
00150   template <typename CharType>
00151   bool WriteStringCore(const CharType *str, unsigned int length,
00152                        MDLocationDescriptor *location);
00153 };
00154 
00155 // Represents an untyped allocated chunk
00156 class UntypedMDRVA {
00157  public:
00158   explicit UntypedMDRVA(MinidumpFileWriter *writer)
00159       : writer_(writer),
00160         position_(writer->position()),
00161         size_(0) {}
00162 
00163   // Allocates |size| bytes.  Must not call more than once.
00164   // Return true on success, or false on failure
00165   bool Allocate(size_t size);
00166 
00167   // Returns the current position or kInvalidMDRVA if allocation failed
00168   inline MDRVA position() const { return position_; }
00169 
00170   // Number of bytes allocated
00171   inline size_t size() const { return size_; }
00172 
00173   // Return size and position
00174   inline MDLocationDescriptor location() const {
00175     MDLocationDescriptor location = { static_cast<uint32_t>(size_),
00176                                       position_ };
00177     return location;
00178   }
00179 
00180   // Copy |size| bytes starting at |src| into the minidump at |position|
00181   // Return true on success, or false on failure
00182   bool Copy(MDRVA position, const void *src, size_t size);
00183 
00184   // Copy |size| bytes from |src| to the current position
00185   inline bool Copy(const void *src, size_t size) {
00186     return Copy(position_, src, size);
00187   }
00188 
00189  protected:
00190   // Writer we associate with
00191   MinidumpFileWriter *writer_;
00192 
00193   // Position of the start of the data
00194   MDRVA position_;
00195 
00196   // Allocated size
00197   size_t size_;
00198 };
00199 
00200 // Represents a Minidump object chunk.  Additional memory can be allocated at
00201 // the end of the object as a:
00202 // - single allocation
00203 // - Array of MDType objects
00204 // - A MDType object followed by an array
00205 template<typename MDType>
00206 class TypedMDRVA : public UntypedMDRVA {
00207  public:
00208   // Constructs an unallocated MDRVA
00209   explicit TypedMDRVA(MinidumpFileWriter *writer)
00210       : UntypedMDRVA(writer),
00211         data_(),
00212         allocation_state_(UNALLOCATED) {}
00213 
00214   inline ~TypedMDRVA() {
00215     // Ensure that the data_ object is written out
00216     if (allocation_state_ != ARRAY)
00217       Flush();
00218   }
00219 
00220   // Address of object data_ of MDType.  This is not declared const as the
00221   // typical usage will be to access the underlying |data_| object as to
00222   // alter its contents.
00223   MDType *get() { return &data_; }
00224 
00225   // Allocates minidump_size<MDType>::size() bytes.
00226   // Must not call more than once.
00227   // Return true on success, or false on failure
00228   bool Allocate();
00229 
00230   // Allocates minidump_size<MDType>::size() + |additional| bytes.
00231   // Must not call more than once.
00232   // Return true on success, or false on failure
00233   bool Allocate(size_t additional);
00234 
00235   // Allocate an array of |count| elements of MDType.
00236   // Must not call more than once.
00237   // Return true on success, or false on failure
00238   bool AllocateArray(size_t count);
00239 
00240   // Allocate an array of |count| elements of |size| after object of MDType
00241   // Must not call more than once.
00242   // Return true on success, or false on failure
00243   bool AllocateObjectAndArray(size_t count, size_t size);
00244 
00245   // Copy |item| to |index|
00246   // Must have been allocated using AllocateArray().
00247   // Return true on success, or false on failure
00248   bool CopyIndex(unsigned int index, MDType *item);
00249 
00250   // Copy |size| bytes starting at |str| to |index|
00251   // Must have been allocated using AllocateObjectAndArray().
00252   // Return true on success, or false on failure
00253   bool CopyIndexAfterObject(unsigned int index, const void *src, size_t size);
00254 
00255   // Write data_
00256   bool Flush();
00257 
00258  private:
00259   enum AllocationState {
00260     UNALLOCATED = 0,
00261     SINGLE_OBJECT,
00262     ARRAY,
00263     SINGLE_OBJECT_WITH_ARRAY
00264   };
00265 
00266   MDType data_;
00267   AllocationState allocation_state_;
00268 };
00269 
00270 }  // namespace google_breakpad
00271 
00272 #endif  // CLIENT_MINIDUMP_FILE_WRITER_H__