1*9712c20fSFrederick Mayle // Copyright 2006 Google LLC 2*9712c20fSFrederick Mayle // 3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without 4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are 5*9712c20fSFrederick Mayle // met: 6*9712c20fSFrederick Mayle // 7*9712c20fSFrederick Mayle // * Redistributions of source code must retain the above copyright 8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer. 9*9712c20fSFrederick Mayle // * Redistributions in binary form must reproduce the above 10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer 11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the 12*9712c20fSFrederick Mayle // distribution. 13*9712c20fSFrederick Mayle // * Neither the name of Google LLC nor the names of its 14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from 15*9712c20fSFrederick Mayle // this software without specific prior written permission. 16*9712c20fSFrederick Mayle // 17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*9712c20fSFrederick Mayle 29*9712c20fSFrederick Mayle // minidump_file_writer.h: Implements file-based minidump generation. It's 30*9712c20fSFrederick Mayle // intended to be used with the Google Breakpad open source crash handling 31*9712c20fSFrederick Mayle // project. 32*9712c20fSFrederick Mayle 33*9712c20fSFrederick Mayle #ifndef CLIENT_MINIDUMP_FILE_WRITER_H__ 34*9712c20fSFrederick Mayle #define CLIENT_MINIDUMP_FILE_WRITER_H__ 35*9712c20fSFrederick Mayle 36*9712c20fSFrederick Mayle #include <string> 37*9712c20fSFrederick Mayle 38*9712c20fSFrederick Mayle #include "google_breakpad/common/minidump_format.h" 39*9712c20fSFrederick Mayle 40*9712c20fSFrederick Mayle namespace google_breakpad { 41*9712c20fSFrederick Mayle 42*9712c20fSFrederick Mayle class UntypedMDRVA; 43*9712c20fSFrederick Mayle template<typename MDType> class TypedMDRVA; 44*9712c20fSFrederick Mayle 45*9712c20fSFrederick Mayle // The user of this class can Open() a file and add minidump streams, data, and 46*9712c20fSFrederick Mayle // strings using the definitions in minidump_format.h. Since this class is 47*9712c20fSFrederick Mayle // expected to be used in a situation where the current process may be 48*9712c20fSFrederick Mayle // damaged, it will not allocate heap memory. 49*9712c20fSFrederick Mayle // Sample usage: 50*9712c20fSFrederick Mayle // MinidumpFileWriter writer; 51*9712c20fSFrederick Mayle // writer.Open("/tmp/minidump.dmp"); 52*9712c20fSFrederick Mayle // TypedMDRVA<MDRawHeader> header(&writer_); 53*9712c20fSFrederick Mayle // header.Allocate(); 54*9712c20fSFrederick Mayle // header->get()->signature = MD_HEADER_SIGNATURE; 55*9712c20fSFrederick Mayle // : 56*9712c20fSFrederick Mayle // writer.Close(); 57*9712c20fSFrederick Mayle // 58*9712c20fSFrederick Mayle // An alternative is to use SetFile and provide a file descriptor: 59*9712c20fSFrederick Mayle // MinidumpFileWriter writer; 60*9712c20fSFrederick Mayle // writer.SetFile(minidump_fd); 61*9712c20fSFrederick Mayle // TypedMDRVA<MDRawHeader> header(&writer_); 62*9712c20fSFrederick Mayle // header.Allocate(); 63*9712c20fSFrederick Mayle // header->get()->signature = MD_HEADER_SIGNATURE; 64*9712c20fSFrederick Mayle // : 65*9712c20fSFrederick Mayle // writer.Close(); 66*9712c20fSFrederick Mayle 67*9712c20fSFrederick Mayle class MinidumpFileWriter { 68*9712c20fSFrederick Mayle public: 69*9712c20fSFrederick Mayle // Invalid MDRVA (Minidump Relative Virtual Address) 70*9712c20fSFrederick Mayle // returned on failed allocation 71*9712c20fSFrederick Mayle static const MDRVA kInvalidMDRVA; 72*9712c20fSFrederick Mayle 73*9712c20fSFrederick Mayle MinidumpFileWriter(); 74*9712c20fSFrederick Mayle ~MinidumpFileWriter(); 75*9712c20fSFrederick Mayle 76*9712c20fSFrederick Mayle // Open |path| as the destination of the minidump data. If |path| already 77*9712c20fSFrederick Mayle // exists, then Open() will fail. 78*9712c20fSFrederick Mayle // Return true on success, or false on failure. 79*9712c20fSFrederick Mayle bool Open(const char* path); 80*9712c20fSFrederick Mayle 81*9712c20fSFrederick Mayle // Sets the file descriptor |file| as the destination of the minidump data. 82*9712c20fSFrederick Mayle // Can be used as an alternative to Open() when a file descriptor is 83*9712c20fSFrederick Mayle // available. 84*9712c20fSFrederick Mayle // Note that |fd| is not closed when the instance of MinidumpFileWriter is 85*9712c20fSFrederick Mayle // destroyed. 86*9712c20fSFrederick Mayle void SetFile(const int file); 87*9712c20fSFrederick Mayle 88*9712c20fSFrederick Mayle // Close the current file (that was either created when Open was called, or 89*9712c20fSFrederick Mayle // specified with SetFile). 90*9712c20fSFrederick Mayle // Return true on success, or false on failure. 91*9712c20fSFrederick Mayle bool Close(); 92*9712c20fSFrederick Mayle 93*9712c20fSFrederick Mayle // Copy the contents of |str| to a MDString and write it to the file. 94*9712c20fSFrederick Mayle // |str| is expected to be either UTF-16 or UTF-32 depending on the size 95*9712c20fSFrederick Mayle // of wchar_t. 96*9712c20fSFrederick Mayle // Maximum |length| of characters to copy from |str|, or specify 0 to use the 97*9712c20fSFrederick Mayle // entire NULL terminated string. Copying will stop at the first NULL. 98*9712c20fSFrederick Mayle // |location| the allocated location 99*9712c20fSFrederick Mayle // Return true on success, or false on failure 100*9712c20fSFrederick Mayle bool WriteString(const wchar_t* str, unsigned int length, 101*9712c20fSFrederick Mayle MDLocationDescriptor* location); 102*9712c20fSFrederick Mayle 103*9712c20fSFrederick Mayle // Same as above, except with |str| as a UTF-8 string 104*9712c20fSFrederick Mayle bool WriteString(const char* str, unsigned int length, 105*9712c20fSFrederick Mayle MDLocationDescriptor* location); 106*9712c20fSFrederick Mayle 107*9712c20fSFrederick Mayle // Write |size| bytes starting at |src| into the current position. 108*9712c20fSFrederick Mayle // Return true on success and set |output| to position, or false on failure 109*9712c20fSFrederick Mayle bool WriteMemory(const void* src, size_t size, MDMemoryDescriptor* output); 110*9712c20fSFrederick Mayle 111*9712c20fSFrederick Mayle // Copies |size| bytes from |src| to |position| 112*9712c20fSFrederick Mayle // Return true on success, or false on failure 113*9712c20fSFrederick Mayle bool Copy(MDRVA position, const void* src, ssize_t size); 114*9712c20fSFrederick Mayle 115*9712c20fSFrederick Mayle // Return the current position for writing to the minidump position()116*9712c20fSFrederick Mayle inline MDRVA position() const { return position_; } 117*9712c20fSFrederick Mayle 118*9712c20fSFrederick Mayle private: 119*9712c20fSFrederick Mayle friend class UntypedMDRVA; 120*9712c20fSFrederick Mayle 121*9712c20fSFrederick Mayle // Allocates an area of |size| bytes. 122*9712c20fSFrederick Mayle // Returns the position of the allocation, or kInvalidMDRVA if it was 123*9712c20fSFrederick Mayle // unable to allocate the bytes. 124*9712c20fSFrederick Mayle MDRVA Allocate(size_t size); 125*9712c20fSFrederick Mayle 126*9712c20fSFrederick Mayle // The file descriptor for the output file. 127*9712c20fSFrederick Mayle int file_; 128*9712c20fSFrederick Mayle 129*9712c20fSFrederick Mayle // Whether |file_| should be closed when the instance is destroyed. 130*9712c20fSFrederick Mayle bool close_file_when_destroyed_; 131*9712c20fSFrederick Mayle 132*9712c20fSFrederick Mayle // Current position in buffer 133*9712c20fSFrederick Mayle MDRVA position_; 134*9712c20fSFrederick Mayle 135*9712c20fSFrederick Mayle // Current allocated size 136*9712c20fSFrederick Mayle size_t size_; 137*9712c20fSFrederick Mayle 138*9712c20fSFrederick Mayle // Copy |length| characters from |str| to |mdstring|. These are distinct 139*9712c20fSFrederick Mayle // because the underlying MDString is a UTF-16 based string. The wchar_t 140*9712c20fSFrederick Mayle // variant may need to create a MDString that has more characters than the 141*9712c20fSFrederick Mayle // source |str|, whereas the UTF-8 variant may coalesce characters to form 142*9712c20fSFrederick Mayle // a single UTF-16 character. 143*9712c20fSFrederick Mayle bool CopyStringToMDString(const wchar_t* str, unsigned int length, 144*9712c20fSFrederick Mayle TypedMDRVA<MDString>* mdstring); 145*9712c20fSFrederick Mayle bool CopyStringToMDString(const char* str, unsigned int length, 146*9712c20fSFrederick Mayle TypedMDRVA<MDString>* mdstring); 147*9712c20fSFrederick Mayle 148*9712c20fSFrederick Mayle // The common templated code for writing a string 149*9712c20fSFrederick Mayle template <typename CharType> 150*9712c20fSFrederick Mayle bool WriteStringCore(const CharType* str, unsigned int length, 151*9712c20fSFrederick Mayle MDLocationDescriptor* location); 152*9712c20fSFrederick Mayle }; 153*9712c20fSFrederick Mayle 154*9712c20fSFrederick Mayle // Represents an untyped allocated chunk 155*9712c20fSFrederick Mayle class UntypedMDRVA { 156*9712c20fSFrederick Mayle public: UntypedMDRVA(MinidumpFileWriter * writer)157*9712c20fSFrederick Mayle explicit UntypedMDRVA(MinidumpFileWriter* writer) 158*9712c20fSFrederick Mayle : writer_(writer), 159*9712c20fSFrederick Mayle position_(writer->position()), 160*9712c20fSFrederick Mayle size_(0) {} 161*9712c20fSFrederick Mayle 162*9712c20fSFrederick Mayle // Allocates |size| bytes. Must not call more than once. 163*9712c20fSFrederick Mayle // Return true on success, or false on failure 164*9712c20fSFrederick Mayle bool Allocate(size_t size); 165*9712c20fSFrederick Mayle 166*9712c20fSFrederick Mayle // Returns the current position or kInvalidMDRVA if allocation failed position()167*9712c20fSFrederick Mayle inline MDRVA position() const { return position_; } 168*9712c20fSFrederick Mayle 169*9712c20fSFrederick Mayle // Number of bytes allocated size()170*9712c20fSFrederick Mayle inline size_t size() const { return size_; } 171*9712c20fSFrederick Mayle 172*9712c20fSFrederick Mayle // Return size and position location()173*9712c20fSFrederick Mayle inline MDLocationDescriptor location() const { 174*9712c20fSFrederick Mayle MDLocationDescriptor location = { static_cast<uint32_t>(size_), 175*9712c20fSFrederick Mayle position_ }; 176*9712c20fSFrederick Mayle return location; 177*9712c20fSFrederick Mayle } 178*9712c20fSFrederick Mayle 179*9712c20fSFrederick Mayle // Copy |size| bytes starting at |src| into the minidump at |position| 180*9712c20fSFrederick Mayle // Return true on success, or false on failure 181*9712c20fSFrederick Mayle bool Copy(MDRVA position, const void* src, size_t size); 182*9712c20fSFrederick Mayle 183*9712c20fSFrederick Mayle // Copy |size| bytes from |src| to the current position Copy(const void * src,size_t size)184*9712c20fSFrederick Mayle inline bool Copy(const void* src, size_t size) { 185*9712c20fSFrederick Mayle return Copy(position_, src, size); 186*9712c20fSFrederick Mayle } 187*9712c20fSFrederick Mayle 188*9712c20fSFrederick Mayle protected: 189*9712c20fSFrederick Mayle // Writer we associate with 190*9712c20fSFrederick Mayle MinidumpFileWriter* writer_; 191*9712c20fSFrederick Mayle 192*9712c20fSFrederick Mayle // Position of the start of the data 193*9712c20fSFrederick Mayle MDRVA position_; 194*9712c20fSFrederick Mayle 195*9712c20fSFrederick Mayle // Allocated size 196*9712c20fSFrederick Mayle size_t size_; 197*9712c20fSFrederick Mayle }; 198*9712c20fSFrederick Mayle 199*9712c20fSFrederick Mayle // Represents a Minidump object chunk. Additional memory can be allocated at 200*9712c20fSFrederick Mayle // the end of the object as a: 201*9712c20fSFrederick Mayle // - single allocation 202*9712c20fSFrederick Mayle // - Array of MDType objects 203*9712c20fSFrederick Mayle // - A MDType object followed by an array 204*9712c20fSFrederick Mayle template<typename MDType> 205*9712c20fSFrederick Mayle class TypedMDRVA : public UntypedMDRVA { 206*9712c20fSFrederick Mayle public: 207*9712c20fSFrederick Mayle // Constructs an unallocated MDRVA TypedMDRVA(MinidumpFileWriter * writer)208*9712c20fSFrederick Mayle explicit TypedMDRVA(MinidumpFileWriter* writer) 209*9712c20fSFrederick Mayle : UntypedMDRVA(writer), 210*9712c20fSFrederick Mayle data_(), 211*9712c20fSFrederick Mayle allocation_state_(UNALLOCATED) {} 212*9712c20fSFrederick Mayle ~TypedMDRVA()213*9712c20fSFrederick Mayle inline ~TypedMDRVA() { 214*9712c20fSFrederick Mayle // Ensure that the data_ object is written out 215*9712c20fSFrederick Mayle if (allocation_state_ != ARRAY) 216*9712c20fSFrederick Mayle Flush(); 217*9712c20fSFrederick Mayle } 218*9712c20fSFrederick Mayle 219*9712c20fSFrederick Mayle // Address of object data_ of MDType. This is not declared const as the 220*9712c20fSFrederick Mayle // typical usage will be to access the underlying |data_| object as to 221*9712c20fSFrederick Mayle // alter its contents. get()222*9712c20fSFrederick Mayle MDType* get() { return &data_; } 223*9712c20fSFrederick Mayle 224*9712c20fSFrederick Mayle // Allocates minidump_size<MDType>::size() bytes. 225*9712c20fSFrederick Mayle // Must not call more than once. 226*9712c20fSFrederick Mayle // Return true on success, or false on failure 227*9712c20fSFrederick Mayle bool Allocate(); 228*9712c20fSFrederick Mayle 229*9712c20fSFrederick Mayle // Allocates minidump_size<MDType>::size() + |additional| bytes. 230*9712c20fSFrederick Mayle // Must not call more than once. 231*9712c20fSFrederick Mayle // Return true on success, or false on failure 232*9712c20fSFrederick Mayle bool Allocate(size_t additional); 233*9712c20fSFrederick Mayle 234*9712c20fSFrederick Mayle // Allocate an array of |count| elements of MDType. 235*9712c20fSFrederick Mayle // Must not call more than once. 236*9712c20fSFrederick Mayle // Return true on success, or false on failure 237*9712c20fSFrederick Mayle bool AllocateArray(size_t count); 238*9712c20fSFrederick Mayle 239*9712c20fSFrederick Mayle // Allocate an array of |count| elements of |size| after object of MDType 240*9712c20fSFrederick Mayle // Must not call more than once. 241*9712c20fSFrederick Mayle // Return true on success, or false on failure 242*9712c20fSFrederick Mayle bool AllocateObjectAndArray(size_t count, size_t size); 243*9712c20fSFrederick Mayle 244*9712c20fSFrederick Mayle // Copy |item| to |index| 245*9712c20fSFrederick Mayle // Must have been allocated using AllocateArray(). 246*9712c20fSFrederick Mayle // Return true on success, or false on failure 247*9712c20fSFrederick Mayle bool CopyIndex(unsigned int index, MDType* item); 248*9712c20fSFrederick Mayle 249*9712c20fSFrederick Mayle // Copy |size| bytes starting at |str| to |index| 250*9712c20fSFrederick Mayle // Must have been allocated using AllocateObjectAndArray(). 251*9712c20fSFrederick Mayle // Return true on success, or false on failure 252*9712c20fSFrederick Mayle bool CopyIndexAfterObject(unsigned int index, const void* src, size_t size); 253*9712c20fSFrederick Mayle 254*9712c20fSFrederick Mayle // Write data_ 255*9712c20fSFrederick Mayle bool Flush(); 256*9712c20fSFrederick Mayle 257*9712c20fSFrederick Mayle private: 258*9712c20fSFrederick Mayle enum AllocationState { 259*9712c20fSFrederick Mayle UNALLOCATED = 0, 260*9712c20fSFrederick Mayle SINGLE_OBJECT, 261*9712c20fSFrederick Mayle ARRAY, 262*9712c20fSFrederick Mayle SINGLE_OBJECT_WITH_ARRAY 263*9712c20fSFrederick Mayle }; 264*9712c20fSFrederick Mayle 265*9712c20fSFrederick Mayle MDType data_; 266*9712c20fSFrederick Mayle AllocationState allocation_state_; 267*9712c20fSFrederick Mayle }; 268*9712c20fSFrederick Mayle 269*9712c20fSFrederick Mayle } // namespace google_breakpad 270*9712c20fSFrederick Mayle 271*9712c20fSFrederick Mayle #endif // CLIENT_MINIDUMP_FILE_WRITER_H__ 272