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