251 lines
8.6 KiB
C
251 lines
8.6 KiB
C
|
// Copyright (c) 2006, Google Inc.
|
||
|
// All rights reserved.
|
||
|
//
|
||
|
// Redistribution and use in source and binary forms, with or without
|
||
|
// modification, are permitted provided that the following conditions are
|
||
|
// met:
|
||
|
//
|
||
|
// * Redistributions of source code must retain the above copyright
|
||
|
// notice, this list of conditions and the following disclaimer.
|
||
|
// * Redistributions in binary form must reproduce the above
|
||
|
// copyright notice, this list of conditions and the following disclaimer
|
||
|
// in the documentation and/or other materials provided with the
|
||
|
// distribution.
|
||
|
// * Neither the name of Google Inc. nor the names of its
|
||
|
// contributors may be used to endorse or promote products derived from
|
||
|
// this software without specific prior written permission.
|
||
|
//
|
||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
||
|
// minidump_file_writer.h: Implements file-based minidump generation. It's
|
||
|
// intended to be used with the Google Breakpad open source crash handling
|
||
|
// project.
|
||
|
|
||
|
#ifndef CLIENT_MINIDUMP_FILE_WRITER_H__
|
||
|
#define CLIENT_MINIDUMP_FILE_WRITER_H__
|
||
|
|
||
|
#include <string>
|
||
|
|
||
|
#include "google_breakpad/common/minidump_format.h"
|
||
|
|
||
|
namespace google_breakpad {
|
||
|
|
||
|
class UntypedMDRVA;
|
||
|
template<typename MDType> class TypedMDRVA;
|
||
|
|
||
|
// The user of this class can Open() a file and add minidump streams, data, and
|
||
|
// strings using the definitions in minidump_format.h. Since this class is
|
||
|
// expected to be used in a situation where the current process may be
|
||
|
// damaged, it will not allocate heap memory.
|
||
|
// Sample usage:
|
||
|
// MinidumpFileWriter writer;
|
||
|
// writer.Open("/tmp/minidump.dmp");
|
||
|
// TypedMDRVA<MDRawHeader> header(&writer_);
|
||
|
// header.Allocate();
|
||
|
// header->get()->signature = MD_HEADER_SIGNATURE;
|
||
|
// :
|
||
|
// writer.Close();
|
||
|
class MinidumpFileWriter {
|
||
|
public:
|
||
|
// Invalid MDRVA (Minidump Relative Virtual Address)
|
||
|
// returned on failed allocation
|
||
|
static const MDRVA kInvalidMDRVA;
|
||
|
|
||
|
MinidumpFileWriter();
|
||
|
~MinidumpFileWriter();
|
||
|
|
||
|
// Open |path| as the destination of the minidump data. Any existing file
|
||
|
// will be overwritten.
|
||
|
// Return true on success, or false on failure
|
||
|
bool Open(const char *path);
|
||
|
|
||
|
// Close the current file
|
||
|
// Return true on success, or false on failure
|
||
|
bool Close();
|
||
|
|
||
|
// Copy the contents of |str| to a MDString and write it to the file.
|
||
|
// |str| is expected to be either UTF-16 or UTF-32 depending on the size
|
||
|
// of wchar_t.
|
||
|
// Maximum |length| of characters to copy from |str|, or specify 0 to use the
|
||
|
// entire NULL terminated string. Copying will stop at the first NULL.
|
||
|
// |location| the allocated location
|
||
|
// Return true on success, or false on failure
|
||
|
bool WriteString(const wchar_t *str, unsigned int length,
|
||
|
MDLocationDescriptor *location);
|
||
|
|
||
|
// Same as above, except with |str| as a UTF-8 string
|
||
|
bool WriteString(const char *str, unsigned int length,
|
||
|
MDLocationDescriptor *location);
|
||
|
|
||
|
// Write |size| bytes starting at |src| into the current position.
|
||
|
// Return true on success and set |output| to position, or false on failure
|
||
|
bool WriteMemory(const void *src, size_t size, MDMemoryDescriptor *output);
|
||
|
|
||
|
// Copies |size| bytes from |src| to |position|
|
||
|
// Return true on success, or false on failure
|
||
|
bool Copy(MDRVA position, const void *src, ssize_t size);
|
||
|
|
||
|
// Return the current position for writing to the minidump
|
||
|
inline MDRVA position() const { return position_; }
|
||
|
|
||
|
private:
|
||
|
friend class UntypedMDRVA;
|
||
|
|
||
|
// Allocates an area of |size| bytes.
|
||
|
// Returns the position of the allocation, or kInvalidMDRVA if it was
|
||
|
// unable to allocate the bytes.
|
||
|
MDRVA Allocate(size_t size);
|
||
|
|
||
|
// The file descriptor for the output file
|
||
|
int file_;
|
||
|
|
||
|
// Current position in buffer
|
||
|
MDRVA position_;
|
||
|
|
||
|
// Current allocated size
|
||
|
size_t size_;
|
||
|
|
||
|
// Copy |length| characters from |str| to |mdstring|. These are distinct
|
||
|
// because the underlying MDString is a UTF-16 based string. The wchar_t
|
||
|
// variant may need to create a MDString that has more characters than the
|
||
|
// source |str|, whereas the UTF-8 variant may coalesce characters to form
|
||
|
// a single UTF-16 character.
|
||
|
bool CopyStringToMDString(const wchar_t *str, unsigned int length,
|
||
|
TypedMDRVA<MDString> *mdstring);
|
||
|
bool CopyStringToMDString(const char *str, unsigned int length,
|
||
|
TypedMDRVA<MDString> *mdstring);
|
||
|
|
||
|
// The common templated code for writing a string
|
||
|
template <typename CharType>
|
||
|
bool WriteStringCore(const CharType *str, unsigned int length,
|
||
|
MDLocationDescriptor *location);
|
||
|
};
|
||
|
|
||
|
// Represents an untyped allocated chunk
|
||
|
class UntypedMDRVA {
|
||
|
public:
|
||
|
explicit UntypedMDRVA(MinidumpFileWriter *writer)
|
||
|
: writer_(writer),
|
||
|
position_(writer->position()),
|
||
|
size_(0) {}
|
||
|
|
||
|
// Allocates |size| bytes. Must not call more than once.
|
||
|
// Return true on success, or false on failure
|
||
|
bool Allocate(size_t size);
|
||
|
|
||
|
// Returns the current position or kInvalidMDRVA if allocation failed
|
||
|
inline MDRVA position() const { return position_; }
|
||
|
|
||
|
// Number of bytes allocated
|
||
|
inline size_t size() const { return size_; }
|
||
|
|
||
|
// Return size and position
|
||
|
inline MDLocationDescriptor location() const {
|
||
|
MDLocationDescriptor location = { static_cast<int>(size_), position_ };
|
||
|
return location;
|
||
|
}
|
||
|
|
||
|
// Copy |size| bytes starting at |src| into the minidump at |position|
|
||
|
// Return true on success, or false on failure
|
||
|
bool Copy(MDRVA position, const void *src, size_t size);
|
||
|
|
||
|
// Copy |size| bytes from |src| to the current position
|
||
|
inline bool Copy(const void *src, size_t size) {
|
||
|
return Copy(position_, src, size);
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
// Writer we associate with
|
||
|
MinidumpFileWriter *writer_;
|
||
|
|
||
|
// Position of the start of the data
|
||
|
MDRVA position_;
|
||
|
|
||
|
// Allocated size
|
||
|
size_t size_;
|
||
|
};
|
||
|
|
||
|
// Represents a Minidump object chunk. Additional memory can be allocated at
|
||
|
// the end of the object as a:
|
||
|
// - single allocation
|
||
|
// - Array of MDType objects
|
||
|
// - A MDType object followed by an array
|
||
|
template<typename MDType>
|
||
|
class TypedMDRVA : public UntypedMDRVA {
|
||
|
public:
|
||
|
// Constructs an unallocated MDRVA
|
||
|
explicit TypedMDRVA(MinidumpFileWriter *writer)
|
||
|
: UntypedMDRVA(writer),
|
||
|
data_(),
|
||
|
allocation_state_(UNALLOCATED) {}
|
||
|
|
||
|
inline ~TypedMDRVA() {
|
||
|
// Ensure that the data_ object is written out
|
||
|
if (allocation_state_ != ARRAY)
|
||
|
Flush();
|
||
|
}
|
||
|
|
||
|
// Address of object data_ of MDType. This is not declared const as the
|
||
|
// typical usage will be to access the underlying |data_| object as to
|
||
|
// alter its contents.
|
||
|
MDType *get() { return &data_; }
|
||
|
|
||
|
// Allocates minidump_size<MDType>::size() bytes.
|
||
|
// Must not call more than once.
|
||
|
// Return true on success, or false on failure
|
||
|
bool Allocate();
|
||
|
|
||
|
// Allocates minidump_size<MDType>::size() + |additional| bytes.
|
||
|
// Must not call more than once.
|
||
|
// Return true on success, or false on failure
|
||
|
bool Allocate(size_t additional);
|
||
|
|
||
|
// Allocate an array of |count| elements of MDType.
|
||
|
// Must not call more than once.
|
||
|
// Return true on success, or false on failure
|
||
|
bool AllocateArray(size_t count);
|
||
|
|
||
|
// Allocate an array of |count| elements of |size| after object of MDType
|
||
|
// Must not call more than once.
|
||
|
// Return true on success, or false on failure
|
||
|
bool AllocateObjectAndArray(size_t count, size_t size);
|
||
|
|
||
|
// Copy |item| to |index|
|
||
|
// Must have been allocated using AllocateArray().
|
||
|
// Return true on success, or false on failure
|
||
|
bool CopyIndex(unsigned int index, MDType *item);
|
||
|
|
||
|
// Copy |size| bytes starting at |str| to |index|
|
||
|
// Must have been allocated using AllocateObjectAndArray().
|
||
|
// Return true on success, or false on failure
|
||
|
bool CopyIndexAfterObject(unsigned int index, const void *src, size_t size);
|
||
|
|
||
|
// Write data_
|
||
|
bool Flush();
|
||
|
|
||
|
private:
|
||
|
enum AllocationState {
|
||
|
UNALLOCATED = 0,
|
||
|
SINGLE_OBJECT,
|
||
|
ARRAY,
|
||
|
SINGLE_OBJECT_WITH_ARRAY
|
||
|
};
|
||
|
|
||
|
MDType data_;
|
||
|
AllocationState allocation_state_;
|
||
|
};
|
||
|
|
||
|
} // namespace google_breakpad
|
||
|
|
||
|
#endif // CLIENT_MINIDUMP_FILE_WRITER_H__
|