xref: /aosp_15_r20/external/google-breakpad/src/client/minidump_file_writer.h (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
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