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.
29 :
30 : // minidump_file_writer.h: Implements file-based minidump generation. It's
31 : // intended to be used with the Google Breakpad open source crash handling
32 : // project.
33 :
34 : #ifndef CLIENT_MINIDUMP_FILE_WRITER_H__
35 : #define CLIENT_MINIDUMP_FILE_WRITER_H__
36 :
37 : #include <string>
38 :
39 : #include "google_breakpad/common/minidump_format.h"
40 :
41 : namespace google_breakpad {
42 :
43 : class UntypedMDRVA;
44 : template<typename MDType> class TypedMDRVA;
45 :
46 : // The user of this class can Open() a file and add minidump streams, data, and
47 : // strings using the definitions in minidump_format.h. Since this class is
48 : // expected to be used in a situation where the current process may be
49 : // damaged, it will not allocate heap memory.
50 : // Sample usage:
51 : // MinidumpFileWriter writer;
52 : // writer.Open("/tmp/minidump.dmp");
53 : // TypedMDRVA<MDRawHeader> header(&writer_);
54 : // header.Allocate();
55 : // header->get()->signature = MD_HEADER_SIGNATURE;
56 : // :
57 : // writer.Close();
58 : class MinidumpFileWriter {
59 : public:
60 : // Invalid MDRVA (Minidump Relative Virtual Address)
61 : // returned on failed allocation
62 : static const MDRVA kInvalidMDRVA;
63 :
64 : MinidumpFileWriter();
65 : ~MinidumpFileWriter();
66 :
67 : // Open |path| as the destination of the minidump data. Any existing file
68 : // will be overwritten.
69 : // Return true on success, or false on failure
70 : bool Open(const char *path);
71 :
72 : // Close the current file
73 : // Return true on success, or false on failure
74 : bool Close();
75 :
76 : // Copy the contents of |str| to a MDString and write it to the file.
77 : // |str| is expected to be either UTF-16 or UTF-32 depending on the size
78 : // of wchar_t.
79 : // Maximum |length| of characters to copy from |str|, or specify 0 to use the
80 : // entire NULL terminated string. Copying will stop at the first NULL.
81 : // |location| the allocated location
82 : // Return true on success, or false on failure
83 : bool WriteString(const wchar_t *str, unsigned int length,
84 : MDLocationDescriptor *location);
85 :
86 : // Same as above, except with |str| as a UTF-8 string
87 : bool WriteString(const char *str, unsigned int length,
88 : MDLocationDescriptor *location);
89 :
90 : // Write |size| bytes starting at |src| into the current position.
91 : // Return true on success and set |output| to position, or false on failure
92 : bool WriteMemory(const void *src, size_t size, MDMemoryDescriptor *output);
93 :
94 : // Copies |size| bytes from |src| to |position|
95 : // Return true on success, or false on failure
96 : bool Copy(MDRVA position, const void *src, ssize_t size);
97 :
98 : // Return the current position for writing to the minidump
99 0 : inline MDRVA position() const { return position_; }
100 :
101 : private:
102 : friend class UntypedMDRVA;
103 :
104 : // Allocates an area of |size| bytes.
105 : // Returns the position of the allocation, or kInvalidMDRVA if it was
106 : // unable to allocate the bytes.
107 : MDRVA Allocate(size_t size);
108 :
109 : // The file descriptor for the output file
110 : int file_;
111 :
112 : // Current position in buffer
113 : MDRVA position_;
114 :
115 : // Current allocated size
116 : size_t size_;
117 :
118 : // Copy |length| characters from |str| to |mdstring|. These are distinct
119 : // because the underlying MDString is a UTF-16 based string. The wchar_t
120 : // variant may need to create a MDString that has more characters than the
121 : // source |str|, whereas the UTF-8 variant may coalesce characters to form
122 : // a single UTF-16 character.
123 : bool CopyStringToMDString(const wchar_t *str, unsigned int length,
124 : TypedMDRVA<MDString> *mdstring);
125 : bool CopyStringToMDString(const char *str, unsigned int length,
126 : TypedMDRVA<MDString> *mdstring);
127 :
128 : // The common templated code for writing a string
129 : template <typename CharType>
130 : bool WriteStringCore(const CharType *str, unsigned int length,
131 : MDLocationDescriptor *location);
132 : };
133 :
134 : // Represents an untyped allocated chunk
135 : class UntypedMDRVA {
136 : public:
137 0 : explicit UntypedMDRVA(MinidumpFileWriter *writer)
138 : : writer_(writer),
139 0 : position_(writer->position()),
140 0 : size_(0) {}
141 :
142 : // Allocates |size| bytes. Must not call more than once.
143 : // Return true on success, or false on failure
144 : bool Allocate(size_t size);
145 :
146 : // Returns the current position or kInvalidMDRVA if allocation failed
147 0 : inline MDRVA position() const { return position_; }
148 :
149 : // Number of bytes allocated
150 0 : inline size_t size() const { return size_; }
151 :
152 : // Return size and position
153 0 : inline MDLocationDescriptor location() const {
154 0 : MDLocationDescriptor location = { static_cast<u_int32_t>(size_), position_ };
155 : return location;
156 : }
157 :
158 : // Copy |size| bytes starting at |src| into the minidump at |position|
159 : // Return true on success, or false on failure
160 : bool Copy(MDRVA position, const void *src, size_t size);
161 :
162 : // Copy |size| bytes from |src| to the current position
163 0 : inline bool Copy(const void *src, size_t size) {
164 0 : return Copy(position_, src, size);
165 : }
166 :
167 : protected:
168 : // Writer we associate with
169 : MinidumpFileWriter *writer_;
170 :
171 : // Position of the start of the data
172 : MDRVA position_;
173 :
174 : // Allocated size
175 : size_t size_;
176 : };
177 :
178 : // Represents a Minidump object chunk. Additional memory can be allocated at
179 : // the end of the object as a:
180 : // - single allocation
181 : // - Array of MDType objects
182 : // - A MDType object followed by an array
183 : template<typename MDType>
184 : class TypedMDRVA : public UntypedMDRVA {
185 : public:
186 : // Constructs an unallocated MDRVA
187 0 : explicit TypedMDRVA(MinidumpFileWriter *writer)
188 : : UntypedMDRVA(writer),
189 : data_(),
190 0 : allocation_state_(UNALLOCATED) {}
191 :
192 0 : inline ~TypedMDRVA() {
193 : // Ensure that the data_ object is written out
194 0 : if (allocation_state_ != ARRAY)
195 0 : Flush();
196 0 : }
197 :
198 : // Address of object data_ of MDType. This is not declared const as the
199 : // typical usage will be to access the underlying |data_| object as to
200 : // alter its contents.
201 0 : MDType *get() { return &data_; }
202 :
203 : // Allocates minidump_size<MDType>::size() bytes.
204 : // Must not call more than once.
205 : // Return true on success, or false on failure
206 : bool Allocate();
207 :
208 : // Allocates minidump_size<MDType>::size() + |additional| bytes.
209 : // Must not call more than once.
210 : // Return true on success, or false on failure
211 : bool Allocate(size_t additional);
212 :
213 : // Allocate an array of |count| elements of MDType.
214 : // Must not call more than once.
215 : // Return true on success, or false on failure
216 : bool AllocateArray(size_t count);
217 :
218 : // Allocate an array of |count| elements of |size| after object of MDType
219 : // Must not call more than once.
220 : // Return true on success, or false on failure
221 : bool AllocateObjectAndArray(size_t count, size_t size);
222 :
223 : // Copy |item| to |index|
224 : // Must have been allocated using AllocateArray().
225 : // Return true on success, or false on failure
226 : bool CopyIndex(unsigned int index, MDType *item);
227 :
228 : // Copy |size| bytes starting at |str| to |index|
229 : // Must have been allocated using AllocateObjectAndArray().
230 : // Return true on success, or false on failure
231 : bool CopyIndexAfterObject(unsigned int index, const void *src, size_t size);
232 :
233 : // Write data_
234 : bool Flush();
235 :
236 : private:
237 : enum AllocationState {
238 : UNALLOCATED = 0,
239 : SINGLE_OBJECT,
240 : ARRAY,
241 : SINGLE_OBJECT_WITH_ARRAY
242 : };
243 :
244 : MDType data_;
245 : AllocationState allocation_state_;
246 : };
247 :
248 : } // namespace google_breakpad
249 :
250 : #endif // CLIENT_MINIDUMP_FILE_WRITER_H__
|