Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
+264
View File
@@ -0,0 +1,264 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_CLIENT_ANNOTATION_H_
#define CRASHPAD_CLIENT_ANNOTATION_H_
#include <algorithm>
#include <atomic>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include "base/logging.h"
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_piece.h"
#include "build/build_config.h"
namespace crashpad {
class AnnotationList;
//! \brief Base class for an annotation, which records a name-value pair of
//! arbitrary data when set.
//!
//! After an annotation is declared, its `value_ptr_` will not be captured in a
//! crash report until a call to \a SetSize() specifies how much data from the
//! value should be recorded.
//!
//! Annotations should be declared with static storage duration.
//!
//! An example declaration and usage:
//!
//! \code
//! // foo.cc:
//!
//! namespace {
//! char g_buffer[1024];
//! crashpad::Annotation g_buffer_annotation(
//! crashpad::Annotation::Type::kString, "buffer_head", g_buffer);
//! } // namespace
//!
//! void OnBufferProduced(size_t n) {
//! // Capture the head of the buffer, in case we crash when parsing it.
//! g_buffer_annotation.SetSize(std::min(64, n));
//!
//! // Start parsing the header.
//! Frobinate(g_buffer, n);
//! }
//! \endcode
//!
//! Annotation objects are not inherently thread-safe. To manipulate them
//! from multiple threads, external synchronization must be used.
//!
//! Annotation objects should never be destroyed. Once they are Set(), they
//! are permanently referenced by a global object.
class Annotation {
public:
//! \brief The maximum length of an annotations name, in bytes.
static constexpr size_t kNameMaxLength = 64;
//! \brief The maximum size of an annotations value, in bytes.
static constexpr size_t kValueMaxSize = 2048;
//! \brief The type used for \a SetSize().
using ValueSizeType = uint32_t;
//! \brief The type of data stored in the annotation.
enum class Type : uint16_t {
//! \brief An invalid annotation. Reserved for internal use.
kInvalid = 0,
//! \brief A `NUL`-terminated C-string.
kString = 1,
//! \brief Clients may declare their own custom types by using values
//! greater than this.
kUserDefinedStart = 0x8000,
};
//! \brief Creates a user-defined Annotation::Type.
//!
//! This exists to remove the casting overhead of `enum class`.
//!
//! \param[in] value A value used to create a user-defined type.
//!
//! \returns The value added to Type::kUserDefinedStart and casted.
constexpr static Type UserDefinedType(uint16_t value) {
using UnderlyingType = std::underlying_type<Type>::type;
// MSVS 2015 doesn't have full C++14 support and complains about local
// variables defined in a constexpr function, which is valid. Avoid them
// and the also-problematic DCHECK until all the infrastructure is updated:
// https://crbug.com/crashpad/201.
#if !defined(OS_WIN) || (defined(_MSC_VER) && _MSC_VER >= 1910)
const UnderlyingType start =
static_cast<UnderlyingType>(Type::kUserDefinedStart);
const UnderlyingType user_type = start + value;
DCHECK(user_type > start) << "User-defined Type is 0 or overflows";
return static_cast<Type>(user_type);
#else
return static_cast<Type>(
static_cast<UnderlyingType>(Type::kUserDefinedStart) + value);
#endif
}
//! \brief Constructs a new annotation.
//!
//! Upon construction, the annotation will not be included in any crash
//! reports until \sa SetSize() is called with a value greater than `0`.
//!
//! \param[in] type The data type of the value of the annotation.
//! \param[in] name A `NUL`-terminated C-string name for the annotation. Names
//! do not have to be unique, though not all crash processors may handle
//! Annotations with the same name. Names should be constexpr data with
//! static storage duration.
//! \param[in] value_ptr A pointer to the value for the annotation. The
//! pointer may not be changed once associated with an annotation, but
//! the data may be mutated.
constexpr Annotation(Type type, const char name[], void* const value_ptr)
: link_node_(nullptr),
name_(name),
value_ptr_(value_ptr),
size_(0),
type_(type) {}
//! \brief Specifies the number of bytes in \a value_ptr_ to include when
//! generating a crash report.
//!
//! A size of `0` indicates that no value should be recorded and is the
//! equivalent of calling \sa Clear().
//!
//! This method does not mutate the data referenced by the annotation, it
//! merely updates the annotation system's bookkeeping.
//!
//! Subclasses of this base class that provide additional Set methods to
//! mutate the value of the annotation must call always call this method.
//!
//! \param[in] size The number of bytes.
void SetSize(ValueSizeType size);
//! \brief Marks the annotation as cleared, indicating the \a value_ptr_
//! should not be included in a crash report.
//!
//! This method does not mutate the data referenced by the annotation, it
//! merely updates the annotation system's bookkeeping.
void Clear();
//! \brief Tests whether the annotation has been set.
bool is_set() const { return size_ > 0; }
Type type() const { return type_; }
ValueSizeType size() const { return size_; }
const char* name() const { return name_; }
const void* value() const { return value_ptr_; }
protected:
friend class AnnotationList;
std::atomic<Annotation*>& link_node() { return link_node_; }
private:
//! \brief Linked list next-node pointer. Accessed only by \sa AnnotationList.
//!
//! This will be null until the first call to \sa SetSize(), after which the
//! presence of the pointer will prevent the node from being added to the
//! list again.
std::atomic<Annotation*> link_node_;
const char* const name_;
void* const value_ptr_;
ValueSizeType size_;
const Type type_;
DISALLOW_COPY_AND_ASSIGN(Annotation);
};
//! \brief An \sa Annotation that stores a `NUL`-terminated C-string value.
//!
//! The storage for the value is allocated by the annotation and the template
//! parameter \a MaxSize controls the maxmium length for the value.
//!
//! It is expected that the string value be valid UTF-8, although this is not
//! validated.
template <Annotation::ValueSizeType MaxSize>
class StringAnnotation : public Annotation {
public:
//! \brief A constructor tag that enables braced initialization in C arrays.
//!
//! \sa StringAnnotation()
enum class Tag { kArray };
//! \brief Constructs a new StringAnnotation with the given \a name.
//!
//! \param[in] name The Annotation name.
constexpr explicit StringAnnotation(const char name[])
: Annotation(Type::kString, name, value_), value_() {}
//! \brief Constructs a new StringAnnotation with the given \a name.
//!
//! This constructor takes the ArrayInitializerTag for use when
//! initializing a C array of annotations. The main constructor is
//! explicit and cannot be brace-initialized. As an example:
//!
//! \code
//! static crashpad::StringAnnotation<32> annotations[] = {
//! {"name-1", crashpad::StringAnnotation<32>::Tag::kArray},
//! {"name-2", crashpad::StringAnnotation<32>::Tag::kArray},
//! {"name-3", crashpad::StringAnnotation<32>::Tag::kArray},
//! };
//! \endcode
//!
//! \param[in] name The Annotation name.
//! \param[in] tag A constructor tag.
constexpr StringAnnotation(const char name[], Tag tag)
: StringAnnotation(name) {}
//! \brief Sets the Annotation's string value.
//!
//! \param[in] value The `NUL`-terminated C-string value.
void Set(const char* value) {
strncpy(value_, value, MaxSize);
SetSize(
std::min(MaxSize, base::saturated_cast<ValueSizeType>(strlen(value))));
}
//! \brief Sets the Annotation's string value.
//!
//! \param[in] string The string value.
void Set(base::StringPiece string) {
Annotation::ValueSizeType size =
std::min(MaxSize, base::saturated_cast<ValueSizeType>(string.size()));
memcpy(value_, string.data(), size);
// Check for no embedded `NUL` characters.
DCHECK(!memchr(value_, '\0', size)) << "embedded NUL";
SetSize(size);
}
const base::StringPiece value() const {
return base::StringPiece(value_, size());
}
private:
// This value is not `NUL`-terminated, since the size is stored by the base
// annotation.
char value_[MaxSize];
DISALLOW_COPY_AND_ASSIGN(StringAnnotation);
};
} // namespace crashpad
#endif // CRASHPAD_CLIENT_ANNOTATION_H_
@@ -0,0 +1,94 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_CLIENT_ANNOTATION_LIST_H_
#define CRASHPAD_CLIENT_ANNOTATION_LIST_H_
#include "base/macros.h"
#include "client/annotation.h"
namespace crashpad {
//! \brief A list that contains all the currently set annotations.
//!
//! An instance of this class must be registered on the \a CrashpadInfo
//! structure in order to use the annotations system. Once a list object has
//! been registered on the CrashpadInfo, a different instance should not
//! be used instead.
class AnnotationList {
public:
AnnotationList();
~AnnotationList();
//! \brief Returns the instance of the list that has been registered on the
//! CrashapdInfo structure.
static AnnotationList* Get();
//! \brief Returns the instace of the list, creating and registering
//! it if one is not already set on the CrashapdInfo structure.
static AnnotationList* Register();
//! \brief Adds \a annotation to the global list. This method does not need
//! to be called by clients directly. The Annotation object will do so
//! automatically.
//!
//! Once an annotation is added to the list, it is not removed. This is
//! because the AnnotationList avoids the use of locks/mutexes, in case it is
//! being manipulated in a compromised context. Instead, an Annotation keeps
//! track of when it has been cleared, which excludes it from a crash report.
//! This design also avoids linear scans of the list when repeatedly setting
//! and/or clearing the value.
void Add(Annotation* annotation);
//! \brief An InputIterator for the AnnotationList.
class Iterator {
public:
~Iterator();
Annotation* operator*() const;
Iterator& operator++();
bool operator==(const Iterator& other) const;
bool operator!=(const Iterator& other) const { return !(*this == other); }
private:
friend class AnnotationList;
Iterator(Annotation* head, const Annotation* tail);
Annotation* curr_;
const Annotation* const tail_;
// Copy and assign are required.
};
//! \brief Returns an iterator to the first element of the annotation list.
Iterator begin();
//! \brief Returns an iterator past the last element of the annotation list.
Iterator end();
private:
// To make it easier for the handler to locate the dummy tail node, store the
// pointer. Placed first for packing.
const Annotation* const tail_pointer_;
// Dummy linked-list head and tail elements of \a Annotation::Type::kInvalid.
Annotation head_;
Annotation tail_;
DISALLOW_COPY_AND_ASSIGN(AnnotationList);
};
} // namespace crashpad
#endif // CRASHPAD_CLIENT_ANNOTATION_LIST_H_
@@ -0,0 +1,48 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_CLIENT_CAPTURE_CONTEXT_MAC_H_
#define CRASHPAD_CLIENT_CAPTURE_CONTEXT_MAC_H_
#include <mach/mach.h>
#include "build/build_config.h"
namespace crashpad {
#if defined(ARCH_CPU_X86_FAMILY)
using NativeCPUContext = x86_thread_state;
#endif
//! \brief Saves the CPU context.
//!
//! The CPU context will be captured as accurately and completely as possible,
//! containing an atomic snapshot at the point of this functions return. This
//! function does not modify any registers.
//!
//! \param[out] cpu_context The structure to store the context in.
//!
//! \note On x86_64, the value for `%%rdi` will be populated with the address of
//! this functions argument, as mandated by the ABI. If the value of
//! `%%rdi` prior to calling this function is needed, it must be obtained
//! separately prior to calling this function. For example:
//! \code
//! uint64_t rdi;
//! asm("movq %%rdi, %0" : "=m"(rdi));
//! \endcode
void CaptureContext(NativeCPUContext* cpu_context);
} // namespace crashpad
#endif // CRASHPAD_CLIENT_CAPTURE_CONTEXT_MAC_H_
@@ -0,0 +1,367 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_CLIENT_CRASH_REPORT_DATABASE_H_
#define CRASHPAD_CLIENT_CRASH_REPORT_DATABASE_H_
#include <time.h>
#include <memory>
#include <string>
#include <vector>
#include "base/files/file_path.h"
#include "base/macros.h"
#include "util/file/file_io.h"
#include "util/misc/metrics.h"
#include "util/misc/uuid.h"
namespace crashpad {
class Settings;
//! \brief An interface for managing a collection of crash report files and
//! metadata associated with the crash reports.
//!
//! All Report objects that are returned by this class are logically const.
//! They are snapshots of the database at the time the query was run, and the
//! data returned is liable to change after the query is executed.
//!
//! The lifecycle of a crash report has three stages:
//!
//! 1. New: A crash report is created with PrepareNewCrashReport(), the
//! the client then writes the report, and then calls
//! FinishedWritingCrashReport() to make the report Pending.
//! 2. Pending: The report has been written but has not been locally
//! processed, or it was has been brought back from 'Completed' state by
//! user request.
//! 3. Completed: The report has been locally processed, either by uploading
//! it to a collection server and calling RecordUploadAttempt(), or by
//! calling SkipReportUpload().
class CrashReportDatabase {
public:
//! \brief A crash report record.
//!
//! This represents the metadata for a crash report, as well as the location
//! of the report itself. A CrashReportDatabase maintains at least this
//! information.
struct Report {
Report();
//! A unique identifier by which this report will always be known to the
//! database.
UUID uuid;
//! The current location of the crash report on the clients filesystem.
//! The location of a crash report may change over time, so the UUID should
//! be used as the canonical identifier.
base::FilePath file_path;
//! An identifier issued to this crash report by a collection server.
std::string id;
//! The time at which the report was generated.
time_t creation_time;
//! Whether this crash report was successfully uploaded to a collection
//! server.
bool uploaded;
//! The last timestamp at which an attempt was made to submit this crash
//! report to a collection server. If this is zero, then the report has
//! never been uploaded. If #uploaded is true, then this timestamp is the
//! time at which the report was uploaded, and no other attempts to upload
//! this report will be made.
time_t last_upload_attempt_time;
//! The number of times an attempt was made to submit this report to
//! a collection server. If this is more than zero, then
//! #last_upload_attempt_time will be set to the timestamp of the most
//! recent attempt.
int upload_attempts;
//! Whether this crash report was explicitly requested by user to be
//! uploaded. This can be true only if report is in the 'pending' state.
bool upload_explicitly_requested;
};
//! \brief A crash report that is in the process of being written.
//!
//! An instance of this struct should be created via PrepareNewCrashReport()
//! and destroyed with FinishedWritingCrashReport().
struct NewReport {
//! The file handle to which the report should be written.
FileHandle handle;
//! A unique identifier by which this report will always be known to the
//! database.
UUID uuid;
//! The path to the crash report being written.
base::FilePath path;
};
//! \brief A scoper to cleanly handle the interface requirement imposed by
//! PrepareNewCrashReport().
//!
//! Calls ErrorWritingCrashReport() upon destruction unless disarmed by
//! calling Disarm(). Armed upon construction.
class CallErrorWritingCrashReport {
public:
//! \brief Arms the object to call ErrorWritingCrashReport() on \a database
//! with an argument of \a new_report on destruction.
CallErrorWritingCrashReport(CrashReportDatabase* database,
NewReport* new_report);
//! \brief Calls ErrorWritingCrashReport() if the object is armed.
~CallErrorWritingCrashReport();
//! \brief Disarms the object so that CallErrorWritingCrashReport() will not
//! be called upon destruction.
void Disarm();
private:
CrashReportDatabase* database_; // weak
NewReport* new_report_; // weak
DISALLOW_COPY_AND_ASSIGN(CallErrorWritingCrashReport);
};
//! \brief The result code for operations performed on a database.
enum OperationStatus {
//! \brief No error occurred.
kNoError = 0,
//! \brief The report that was requested could not be located.
//!
//! This may occur when the report is present in the database but not in a
//! state appropriate for the requested operation, for example, if
//! GetReportForUploading() is called to obtain report thats already in the
//! completed state.
kReportNotFound,
//! \brief An error occured while performing a file operation on a crash
//! report.
//!
//! A database is responsible for managing both the metadata about a report
//! and the actual crash report itself. This error is returned when an
//! error occurred when managing the report file. Additional information
//! will be logged.
kFileSystemError,
//! \brief An error occured while recording metadata for a crash report or
//! database-wide settings.
//!
//! A database is responsible for managing both the metadata about a report
//! and the actual crash report itself. This error is returned when an
//! error occurred when managing the metadata about a crash report or
//! database-wide settings. Additional information will be logged.
kDatabaseError,
//! \brief The operation could not be completed because a concurrent
//! operation affecting the report is occurring.
kBusyError,
//! \brief The report cannot be uploaded by user request as it has already
//! been uploaded.
kCannotRequestUpload,
};
virtual ~CrashReportDatabase() {}
//! \brief Opens a database of crash reports, possibly creating it.
//!
//! \param[in] path A path to the database to be created or opened. If the
//! database does not yet exist, it will be created if possible. Note that
//! for databases implemented as directory structures, existence refers
//! solely to the outermost directory.
//!
//! \return A database object on success, `nullptr` on failure with an error
//! logged.
//!
//! \sa InitializeWithoutCreating
static std::unique_ptr<CrashReportDatabase> Initialize(
const base::FilePath& path);
//! \brief Opens an existing database of crash reports.
//!
//! \param[in] path A path to the database to be opened. If the database does
//! not yet exist, it will not be created. Note that for databases
//! implemented as directory structures, existence refers solely to the
//! outermost directory. On such databases, as long as the outermost
//! directory is present, this method will create the inner structure.
//!
//! \return A database object on success, `nullptr` on failure with an error
//! logged.
//!
//! \sa Initialize
static std::unique_ptr<CrashReportDatabase> InitializeWithoutCreating(
const base::FilePath& path);
//! \brief Returns the Settings object for this database.
//!
//! \return A weak pointer to the Settings object, which is owned by the
//! database.
virtual Settings* GetSettings() = 0;
//! \brief Creates a record of a new crash report.
//!
//! Callers can then write the crash report using the file handle provided.
//! The caller does not own the new crash report record or its file handle,
//! both of which must be explicitly disposed of by calling
//! FinishedWritingCrashReport() or ErrorWritingCrashReport().
//!
//! To arrange to call ErrorWritingCrashReport() during any early return, use
//! CallErrorWritingCrashReport.
//!
//! \param[out] report A NewReport object containing a file handle to which
//! the crash report data should be written. Only valid if this returns
//! #kNoError. The caller must not delete the NewReport object or close
//! the file handle within.
//!
//! \return The operation status code.
virtual OperationStatus PrepareNewCrashReport(NewReport** report) = 0;
//! \brief Informs the database that a crash report has been written.
//!
//! After calling this method, the database is permitted to move and rename
//! the file at NewReport::path.
//!
//! \param[in] report A NewReport obtained with PrepareNewCrashReport(). The
//! NewReport object and file handle within will be invalidated as part of
//! this call.
//! \param[out] uuid The UUID of this crash report.
//!
//! \return The operation status code.
virtual OperationStatus FinishedWritingCrashReport(NewReport* report,
UUID* uuid) = 0;
//! \brief Informs the database that an error occurred while attempting to
//! write a crash report, and that any resources associated with it should
//! be cleaned up.
//!
//! After calling this method, the database is permitted to remove the file at
//! NewReport::path.
//!
//! \param[in] report A NewReport obtained with PrepareNewCrashReport(). The
//! NewReport object and file handle within will be invalidated as part of
//! this call.
//!
//! \return The operation status code.
virtual OperationStatus ErrorWritingCrashReport(NewReport* report) = 0;
//! \brief Returns the crash report record for the unique identifier.
//!
//! \param[in] uuid The crash report record unique identifier.
//! \param[out] report A crash report record. Only valid if this returns
//! #kNoError.
//!
//! \return The operation status code.
virtual OperationStatus LookUpCrashReport(const UUID& uuid,
Report* report) = 0;
//! \brief Returns a list of crash report records that have not been uploaded.
//!
//! \param[out] reports A list of crash report record objects. This must be
//! empty on entry. Only valid if this returns #kNoError.
//!
//! \return The operation status code.
virtual OperationStatus GetPendingReports(std::vector<Report>* reports) = 0;
//! \brief Returns a list of crash report records that have been completed,
//! either by being uploaded or by skipping upload.
//!
//! \param[out] reports A list of crash report record objects. This must be
//! empty on entry. Only valid if this returns #kNoError.
//!
//! \return The operation status code.
virtual OperationStatus GetCompletedReports(std::vector<Report>* reports) = 0;
//! \brief Obtains a report object for uploading to a collection server.
//!
//! The file at Report::file_path should be uploaded by the caller, and then
//! the returned Report object must be disposed of via a call to
//! RecordUploadAttempt().
//!
//! A subsequent call to this method with the same \a uuid is illegal until
//! RecordUploadAttempt() has been called.
//!
//! \param[in] uuid The unique identifier for the crash report record.
//! \param[out] report A crash report record for the report to be uploaded.
//! The caller does not own this object. Only valid if this returns
//! #kNoError.
//!
//! \return The operation status code.
virtual OperationStatus GetReportForUploading(const UUID& uuid,
const Report** report) = 0;
//! \brief Adjusts a crash report records metadata to account for an upload
//! attempt, and updates the last upload attempt time as returned by
//! Settings::GetLastUploadAttemptTime().
//!
//! After calling this method, the database is permitted to move and rename
//! the file at Report::file_path.
//!
//! \param[in] report The report object obtained from
//! GetReportForUploading(). This object is invalidated after this call.
//! \param[in] successful Whether the upload attempt was successful.
//! \param[in] id The identifier assigned to this crash report by the
//! collection server. Must be empty if \a successful is `false`; may be
//! empty if it is `true`.
//!
//! \return The operation status code.
virtual OperationStatus RecordUploadAttempt(const Report* report,
bool successful,
const std::string& id) = 0;
//! \brief Moves a report from the pending state to the completed state, but
//! without the report being uploaded.
//!
//! This can be used if the user has disabled crash report collection, but
//! crash generation is still enabled in the product.
//!
//! \param[in] uuid The unique identifier for the crash report record.
//! \param[in] reason The reason the report upload is being skipped for
//! metrics tracking purposes.
//!
//! \return The operation status code.
virtual OperationStatus SkipReportUpload(
const UUID& uuid,
Metrics::CrashSkippedReason reason) = 0;
//! \brief Deletes a crash report file and its associated metadata.
//!
//! \param[in] uuid The UUID of the report to delete.
//!
//! \return The operation status code.
virtual OperationStatus DeleteReport(const UUID& uuid) = 0;
//! \brief Marks a crash report as explicitly requested to be uploaded by the
//! user and moves it to 'pending' state.
//!
//! \param[in] uuid The unique identifier for the crash report record.
//!
//! \return The operation status code.
virtual OperationStatus RequestUpload(const UUID& uuid) = 0;
protected:
CrashReportDatabase() {}
private:
DISALLOW_COPY_AND_ASSIGN(CrashReportDatabase);
};
} // namespace crashpad
#endif // CRASHPAD_CLIENT_CRASH_REPORT_DATABASE_H_
@@ -0,0 +1,294 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_CLIENT_CRASHPAD_CLIENT_H_
#define CRASHPAD_CLIENT_CRASHPAD_CLIENT_H_
#include <map>
#include <string>
#include <vector>
#include <stdint.h>
#include "base/files/file_path.h"
#include "base/macros.h"
#include "build/build_config.h"
#if defined(OS_MACOSX)
#include "base/mac/scoped_mach_port.h"
#elif defined(OS_WIN)
#include <windows.h>
#include "util/win/scoped_handle.h"
#endif
namespace crashpad {
//! \brief The primary interface for an application to have Crashpad monitor
//! it for crashes.
class CrashpadClient {
public:
CrashpadClient();
~CrashpadClient();
//! \brief Starts a Crashpad handler process, performing any necessary
//! handshake to configure it.
//!
//! This method directs crashes to the Crashpad handler. On macOS, this is
//! applicable to this process and all subsequent child processes. On Windows,
//! child processes must also register by using SetHandlerIPCPipe().
//!
//! On macOS, this method starts a Crashpad handler and obtains a Mach send
//! right corresponding to a receive right held by the handler process. The
//! handler process runs an exception server on this port. This method sets
//! the tasks exception port for `EXC_CRASH`, `EXC_RESOURCE`, and `EXC_GUARD`
//! exceptions to the Mach send right obtained. The handler will be installed
//! with behavior `EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES` and thread
//! state flavor `MACHINE_THREAD_STATE`. Exception ports are inherited, so a
//! Crashpad handler started here will remain the handler for any child
//! processes created after StartHandler() is called. These child processes do
//! not need to call StartHandler() or be aware of Crashpad in any way. The
//! Crashpad handler will receive crashes from child processes that have
//! inherited it as their exception handler even after the process that called
//! StartHandler() exits.
//!
//! On Windows, if \a asynchronous_start is `true`, this function will not
//! directly call `CreateProcess()`, making it suitable for use in a
//! `DllMain()`. In that case, the handler is started from a background
//! thread, deferring the handler's startup. Nevertheless, regardless of the
//! value of \a asynchronous_start, after calling this method, the global
//! unhandled exception filter is set up, and all crashes will be handled by
//! Crashpad. Optionally, use WaitForHandlerStart() to join with the
//! background thread and retrieve the status of handler startup.
//!
//! \param[in] handler The path to a Crashpad handler executable.
//! \param[in] database The path to a Crashpad database. The handler will be
//! started with this path as its `--database` argument.
//! \param[in] metrics_dir The path to an already existing directory where
//! metrics files can be stored. The handler will be started with this
//! path as its `--metrics-dir` argument.
//! \param[in] url The URL of an upload server. The handler will be started
//! with this URL as its `--url` argument.
//! \param[in] annotations Process annotations to set in each crash report.
//! The handler will be started with an `--annotation` argument for each
//! element in this map.
//! \param[in] arguments Additional arguments to pass to the Crashpad handler.
//! Arguments passed in other parameters and arguments required to perform
//! the handshake are the responsibility of this method, and must not be
//! specified in this parameter.
//! \param[in] restartable If `true`, the handler will be restarted if it
//! dies, if this behavior is supported. This option is not available on
//! all platforms, and does not function on all OS versions. If it is
//! not supported, it will be ignored.
//! \param[out] asynchronous_start If `true`, the handler will be started from
//! a background thread. Optionally, WaitForHandlerStart() can be used at
//! a suitable time to retreive the result of background startup. This
//! option is only used on Windows.
//!
//! \return `true` on success, `false` on failure with a message logged.
bool StartHandler(const base::FilePath& handler,
const base::FilePath& database,
const base::FilePath& metrics_dir,
const std::string& url,
const std::map<std::string, std::string>& annotations,
const std::vector<std::string>& arguments,
bool restartable,
bool asynchronous_start);
#if defined(OS_MACOSX) || DOXYGEN
//! \brief Sets the process crash handler to a Mach service registered with
//! the bootstrap server.
//!
//! This method is only defined on macOS.
//!
//! See StartHandler() for more detail on how the port and handler are
//! configured.
//!
//! \param[in] service_name The service name of a Crashpad exception handler
//! service previously registered with the bootstrap server.
//!
//! \return `true` on success, `false` on failure with a message logged.
bool SetHandlerMachService(const std::string& service_name);
//! \brief Sets the process crash handler to a Mach port.
//!
//! This method is only defined on macOS.
//!
//! See StartHandler() for more detail on how the port and handler are
//! configured.
//!
//! \param[in] exception_port An `exception_port_t` corresponding to a
//! Crashpad exception handler service.
//!
//! \return `true` on success, `false` on failure with a message logged.
bool SetHandlerMachPort(base::mac::ScopedMachSendRight exception_port);
//! \brief Retrieves a send right to the process crash handler Mach port.
//!
//! This method is only defined on macOS.
//!
//! This method can be used to obtain the crash handler Mach port when a
//! Crashpad client process wishes to provide a send right to this port to
//! another process. The IPC mechanism used to convey the right is under the
//! applications control. If the other process wishes to become a client of
//! the same crash handler, it can provide the transferred right to
//! SetHandlerMachPort().
//!
//! See StartHandler() for more detail on how the port and handler are
//! configured.
//!
//! \return The Mach port set by SetHandlerMachPort(), possibly indirectly by
//! a call to another method such as StartHandler() or
//! SetHandlerMachService(). This method must only be called after a
//! successful call to one of those methods. `MACH_PORT_NULL` on failure
//! with a message logged.
base::mac::ScopedMachSendRight GetHandlerMachPort() const;
#endif
#if defined(OS_WIN) || DOXYGEN
//! \brief Sets the IPC pipe of a presumably-running Crashpad handler process
//! which was started with StartHandler() or by other compatible means
//! and does an IPC message exchange to register this process with the
//! handler. Crashes will be serviced once this method returns.
//!
//! This method is only defined on Windows.
//!
//! This method sets the unhandled exception handler to a local
//! function that when reached will "signal and wait" for the crash handler
//! process to create the dump.
//!
//! \param[in] ipc_pipe The full name of the crash handler IPC pipe. This is
//! a string of the form `&quot;\\.\pipe\NAME&quot;`.
//!
//! \return `true` on success and `false` on failure.
bool SetHandlerIPCPipe(const std::wstring& ipc_pipe);
//! \brief Retrieves the IPC pipe name used to register with the Crashpad
//! handler.
//!
//! This method is only defined on Windows.
//!
//! This method retrieves the IPC pipe name set by SetHandlerIPCPipe(), or a
//! suitable IPC pipe name chosen by StartHandler(). It must only be called
//! after a successful call to one of those methods. It is intended to be used
//! to obtain the IPC pipe name so that it may be passed to other processes,
//! so that they may register with an existing Crashpad handler by calling
//! SetHandlerIPCPipe().
//!
//! \return The full name of the crash handler IPC pipe, a string of the form
//! `&quot;\\.\pipe\NAME&quot;`.
std::wstring GetHandlerIPCPipe() const;
//! \brief When `asynchronous_start` is used with StartHandler(), this method
//! can be used to block until the handler launch has been completed to
//! retrieve status information.
//!
//! This method should not be used unless `asynchronous_start` was `true`.
//!
//! \param[in] timeout_ms The number of milliseconds to wait for a result from
//! the background launch, or `0xffffffff` to block indefinitely.
//!
//! \return `true` if the hander startup succeeded, `false` otherwise, and an
//! error message will have been logged.
bool WaitForHandlerStart(unsigned int timeout_ms);
//! \brief Requests that the handler capture a dump even though there hasn't
//! been a crash.
//!
//! \param[in] context A `CONTEXT`, generally captured by CaptureContext() or
//! similar.
static void DumpWithoutCrash(const CONTEXT& context);
//! \brief Requests that the handler capture a dump using the given \a
//! exception_pointers to get the `EXCEPTION_RECORD` and `CONTEXT`.
//!
//! This function is not necessary in general usage as an unhandled exception
//! filter is installed by StartHandler() or SetHandlerIPCPipe().
//!
//! \param[in] exception_pointers An `EXCEPTION_POINTERS`, as would generally
//! passed to an unhandled exception filter.
static void DumpAndCrash(EXCEPTION_POINTERS* exception_pointers);
//! \brief Requests that the handler capture a dump of a different process.
//!
//! The target process must be an already-registered Crashpad client. An
//! exception will be triggered in the target process, and the regular dump
//! mechanism used. This function will block until the exception in the target
//! process has been handled by the Crashpad handler.
//!
//! This function is unavailable when running on Windows XP and will return
//! `false`.
//!
//! \param[in] process A `HANDLE` identifying the process to be dumped.
//! \param[in] blame_thread If non-null, a `HANDLE` valid in the caller's
//! process, referring to a thread in the target process. If this is
//! supplied, instead of the exception referring to the location where the
//! exception was injected, an exception record will be fabricated that
//! refers to the current location of the given thread.
//! \param[in] exception_code If \a blame_thread is non-null, this will be
//! used as the exception code in the exception record.
//!
//! \return `true` if the exception was triggered successfully.
bool DumpAndCrashTargetProcess(HANDLE process,
HANDLE blame_thread,
DWORD exception_code) const;
enum : uint32_t {
//! \brief The exception code (roughly "Client called") used when
//! DumpAndCrashTargetProcess() triggers an exception in a target
//! process.
//!
//! \note This value does not have any bits of the top nibble set, to avoid
//! confusion with real exception codes which tend to have those bits
//! set.
kTriggeredExceptionCode = 0xcca11ed,
};
#endif
#if defined(OS_MACOSX) || DOXYGEN
//! \brief Configures the process to direct its crashes to the default handler
//! for the operating system.
//!
//! On macOS, this sets the tasks exception port as in SetHandlerMachPort(),
//! but the exception handler used is obtained from
//! SystemCrashReporterHandler(). If the systems crash reporter handler
//! cannot be determined or set, the tasks exception ports for crash-type
//! exceptions are cleared.
//!
//! Use of this function is strongly discouraged.
//!
//! \warning After a call to this function, Crashpad will no longer monitor
//! the process for crashes until a subsequent call to
//! SetHandlerMachPort().
//!
//! \note This is provided as a static function to allow it to be used in
//! situations where a CrashpadClient object is not otherwise available.
//! This may be useful when a child process inherits its parents Crashpad
//! handler, but wants to sever this tie.
static void UseSystemDefaultHandler();
#endif
private:
#if defined(OS_MACOSX)
base::mac::ScopedMachSendRight exception_port_;
#elif defined(OS_WIN)
std::wstring ipc_pipe_;
ScopedKernelHANDLE handler_start_thread_;
#endif // OS_MACOSX
DISALLOW_COPY_AND_ASSIGN(CrashpadClient);
};
} // namespace crashpad
#endif // CRASHPAD_CLIENT_CRASHPAD_CLIENT_H_
@@ -0,0 +1,266 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_CLIENT_CRASHPAD_INFO_H_
#define CRASHPAD_CLIENT_CRASHPAD_INFO_H_
#include <stdint.h>
#include "base/macros.h"
#include "build/build_config.h"
#include "client/annotation_list.h"
#include "client/simple_address_range_bag.h"
#include "client/simple_string_dictionary.h"
#include "util/misc/tri_state.h"
#if defined(OS_WIN)
#include <windows.h>
#endif // OS_WIN
namespace crashpad {
namespace internal {
//! \brief A linked list of blocks representing custom streams in the minidump,
//! with addresses (and size) stored as uint64_t to simplify reading from
//! the handler process.
struct UserDataMinidumpStreamListEntry {
//! \brief The address of the next entry in the linked list.
uint64_t next;
//! \brief The base address of the memory block in the target process' address
//! space that represents the user data stream.
uint64_t base_address;
//! \brief The size of memory block in the target process' address space that
//! represents the user data stream.
uint64_t size;
//! \brief The stream type identifier.
uint32_t stream_type;
};
} // namespace internal
//! \brief A structure that can be used by a Crashpad-enabled program to
//! provide information to the Crashpad crash handler.
//!
//! It is possible for one CrashpadInfo structure to appear in each loaded code
//! module in a process, but from the perspective of the user of the client
//! interface, there is only one global CrashpadInfo structure, located in the
//! module that contains the client interface code.
struct CrashpadInfo {
public:
//! \brief Returns the global CrashpadInfo structure.
static CrashpadInfo* GetCrashpadInfo();
CrashpadInfo();
//! \brief Sets the bag of extra memory ranges to be included in the snapshot.
//!
//! Extra memory ranges may exist in \a address_range_bag at the time that
//! this method is called, or they may be added, removed, or modified in \a
//! address_range_bag after this method is called.
//!
//! TODO(scottmg) This is currently only supported on Windows.
//!
//! \param[in] address_range_bag A bag of address ranges. The CrashpadInfo
//! object does not take ownership of the SimpleAddressRangeBag object.
//! It is the callers responsibility to ensure that this pointer remains
//! valid while it is in effect for a CrashpadInfo object.
void set_extra_memory_ranges(SimpleAddressRangeBag* address_range_bag) {
extra_memory_ranges_ = address_range_bag;
}
//! \brief Sets the simple annotations dictionary.
//!
//! Simple annotations set on a CrashpadInfo structure are interpreted by
//! Crashpad as module-level annotations.
//!
//! Annotations may exist in \a simple_annotations at the time that this
//! method is called, or they may be added, removed, or modified in \a
//! simple_annotations after this method is called.
//!
//! \param[in] simple_annotations A dictionary that maps string keys to string
//! values. The CrashpadInfo object does not take ownership of the
//! SimpleStringDictionary object. It is the callers responsibility to
//! ensure that this pointer remains valid while it is in effect for a
//! CrashpadInfo object.
//!
//! \sa simple_annotations()
void set_simple_annotations(SimpleStringDictionary* simple_annotations) {
simple_annotations_ = simple_annotations;
}
//! \return The simple annotations dictionary.
//!
//! \sa set_simple_annotations()
SimpleStringDictionary* simple_annotations() const {
return simple_annotations_;
}
//! \brief Sets the annotations list.
//!
//! Unlike the \a simple_annotations structure, the \a annotations can
//! typed data and it is not limited to a dictionary form. Annotations are
//! interpreted by Crashpad as module-level annotations.
//!
//! Annotations may exist in \a list at the time that this method is called,
//! or they may be added, removed, or modified in \a list after this method is
//! called.
//!
//! \param[in] list A list of set Annotation objects that maintain arbitrary,
//! typed key-value state. The CrashpadInfo object does not take ownership
//! of the AnnotationsList object. It is the callers responsibility to
//! ensure that this pointer remains valid while it is in effect for a
//! CrashpadInfo object.
//!
//! \sa annotations_list()
//! \sa AnnotationList::Register()
void set_annotations_list(AnnotationList* list) { annotations_list_ = list; }
//! \return The annotations list.
//!
//! \sa set_annotations_list()
//! \sa AnnotationList::Get()
//! \sa AnnotationList::Register()
AnnotationList* annotations_list() const { return annotations_list_; }
//! \brief Enables or disables Crashpad handler processing.
//!
//! When handling an exception, the Crashpad handler will scan all modules in
//! a process. The first one that has a CrashpadInfo structure populated with
//! a value other than #kUnset for this field will dictate whether the handler
//! is functional or not. If all modules with a CrashpadInfo structure specify
//! #kUnset, the handler will be enabled. If disabled, the Crashpad handler
//! will still run and receive exceptions, but will not take any action on an
//! exception on its own behalf, except for the action necessary to determine
//! that it has been disabled.
//!
//! The Crashpad handler should not normally be disabled. More commonly, it
//! is appropriate to disable crash report upload by calling
//! Settings::SetUploadsEnabled().
void set_crashpad_handler_behavior(TriState crashpad_handler_behavior) {
crashpad_handler_behavior_ = crashpad_handler_behavior;
}
//! \brief Enables or disables Crashpad forwarding of exceptions to the
//! systems crash reporter.
//!
//! When handling an exception, the Crashpad handler will scan all modules in
//! a process. The first one that has a CrashpadInfo structure populated with
//! a value other than #kUnset for this field will dictate whether the
//! exception is forwarded to the systems crash reporter. If all modules with
//! a CrashpadInfo structure specify #kUnset, forwarding will be enabled.
//! Unless disabled, forwarding may still occur if the Crashpad handler is
//! disabled by SetCrashpadHandlerState(). Even when forwarding is enabled,
//! the Crashpad handler may choose not to forward all exceptions to the
//! systems crash reporter in cases where it has reason to believe that the
//! systems crash reporter would not normally have handled the exception in
//! Crashpads absence.
void set_system_crash_reporter_forwarding(
TriState system_crash_reporter_forwarding) {
system_crash_reporter_forwarding_ = system_crash_reporter_forwarding;
}
//! \brief Enables or disables Crashpad capturing indirectly referenced memory
//! in the minidump.
//!
//! When handling an exception, the Crashpad handler will scan all modules in
//! a process. The first one that has a CrashpadInfo structure populated with
//! a value other than #kUnset for this field will dictate whether the extra
//! memory is captured.
//!
//! This causes Crashpad to include pages of data referenced by locals or
//! other stack memory. Turning this on can increase the size of the minidump
//! significantly.
//!
//! \param[in] gather_indirectly_referenced_memory Whether extra memory should
//! be gathered.
//! \param[in] limit The amount of memory in bytes after which no more
//! indirectly gathered memory should be captured. This value is only used
//! when \a gather_indirectly_referenced_memory is TriState::kEnabled.
void set_gather_indirectly_referenced_memory(
TriState gather_indirectly_referenced_memory,
uint32_t limit) {
gather_indirectly_referenced_memory_ = gather_indirectly_referenced_memory;
indirectly_referenced_memory_cap_ = limit;
}
//! \brief Adds a custom stream to the minidump.
//!
//! The memory block referenced by \a data and \a size will added to the
//! minidump as separate stream with type \a stream_type. The memory referred
//! to by \a data and \a size is owned by the caller and must remain valid
//! while it is in effect for the CrashpadInfo object.
//!
//! Note that streams will appear in the minidump in the reverse order to
//! which they are added.
//!
//! TODO(scottmg) This is currently only supported on Windows.
//!
//! \param[in] stream_type The stream type identifier to use. This should be
//! normally be larger than `MINIDUMP_STREAM_TYPE::LastReservedStream`
//! which is `0xffff`.
//! \param[in] data The base pointer of the stream data.
//! \param[in] size The size of the stream data.
void AddUserDataMinidumpStream(uint32_t stream_type,
const void* data,
size_t size);
enum : uint32_t {
kSignature = 'CPad',
};
private:
// The compiler wont necessarily see anyone using these fields, but it
// shouldnt warn about that. These fields arent intended for use by the
// process theyre found in, theyre supposed to be read by the crash
// reporting process.
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-private-field"
#endif
// Fields present in version 1, subject to a check of the size_ field:
uint32_t signature_; // kSignature
uint32_t size_; // The size of the entire CrashpadInfo structure.
uint32_t version_; // kCrashpadInfoVersion
uint32_t indirectly_referenced_memory_cap_;
uint32_t padding_0_;
TriState crashpad_handler_behavior_;
TriState system_crash_reporter_forwarding_;
TriState gather_indirectly_referenced_memory_;
uint8_t padding_1_;
SimpleAddressRangeBag* extra_memory_ranges_; // weak
SimpleStringDictionary* simple_annotations_; // weak
internal::UserDataMinidumpStreamListEntry* user_data_minidump_stream_head_;
AnnotationList* annotations_list_; // weak
// Its generally safe to add new fields without changing
// kCrashpadInfoVersion, because readers should check size_ and ignore fields
// that arent present, as well as unknown fields.
//
// Adding fields? Consider snapshot/crashpad_info_size_test_module.cc too.
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
DISALLOW_COPY_AND_ASSIGN(CrashpadInfo);
};
} // namespace crashpad
#endif // CRASHPAD_CLIENT_CRASHPAD_INFO_H_
@@ -0,0 +1,148 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_CLIENT_PRUNE_CRASH_REPORTS_H_
#define CRASHPAD_CLIENT_PRUNE_CRASH_REPORTS_H_
#include <sys/types.h>
#include <time.h>
#include <memory>
#include "base/macros.h"
#include "client/crash_report_database.h"
namespace crashpad {
class PruneCondition;
//! \brief Deletes crash reports from \a database that match \a condition.
//!
//! This function can be used to remove old or large reports from the database.
//! The \a condition will be evaluated against each report in the \a database,
//! sorted in descending order by CrashReportDatabase::Report::creation_time.
//! This guarantee allows conditions to be stateful.
//!
//! \param[in] database The database from which crash reports will be deleted.
//! \param[in] condition The condition against which all reports in the database
//! will be evaluated.
void PruneCrashReportDatabase(CrashReportDatabase* database,
PruneCondition* condition);
std::unique_ptr<PruneCondition> GetDefaultDatabasePruneCondition();
//! \brief An abstract base class for evaluating crash reports for deletion.
//!
//! When passed to PruneCrashReportDatabase(), each crash report in the
//! database will be evaluated according to ShouldPruneReport(). The reports
//! are evaluated serially in descending sort order by
//! CrashReportDatabase::Report::creation_time.
class PruneCondition {
public:
//! \brief Returns a sensible default condition for removing obsolete crash
//! reports.
//!
//! The default is to keep reports for one year or a maximum database size
//! of 128 MB.
//!
//! \return A PruneCondition for use with PruneCrashReportDatabase().
static std::unique_ptr<PruneCondition> GetDefault();
virtual ~PruneCondition() {}
//! \brief Evaluates a crash report for deletion.
//!
//! \param[in] report The crash report to evaluate.
//!
//! \return `true` if the crash report should be deleted, `false` if it
//! should be kept.
virtual bool ShouldPruneReport(const CrashReportDatabase::Report& report) = 0;
};
//! \brief A PruneCondition that deletes reports older than the specified number
//! days.
class AgePruneCondition final : public PruneCondition {
public:
//! \brief Creates a PruneCondition based on Report::creation_time.
//!
//! \param[in] max_age_in_days Reports created more than this many days ago
//! will be deleted.
explicit AgePruneCondition(int max_age_in_days);
~AgePruneCondition();
bool ShouldPruneReport(const CrashReportDatabase::Report& report) override;
private:
const time_t oldest_report_time_;
DISALLOW_COPY_AND_ASSIGN(AgePruneCondition);
};
//! \brief A PruneCondition that deletes older reports to keep the total
//! Crashpad database size under the specified limit.
class DatabaseSizePruneCondition final : public PruneCondition {
public:
//! \brief Creates a PruneCondition that will keep newer reports, until the
//! sum of the size of all reports is not smaller than \a max_size_in_kb.
//! After the limit is reached, older reports will be pruned.
//!
//! \param[in] max_size_in_kb The maximum number of kilobytes that all crash
//! reports should consume.
explicit DatabaseSizePruneCondition(size_t max_size_in_kb);
~DatabaseSizePruneCondition();
bool ShouldPruneReport(const CrashReportDatabase::Report& report) override;
private:
const size_t max_size_in_kb_;
size_t measured_size_in_kb_;
DISALLOW_COPY_AND_ASSIGN(DatabaseSizePruneCondition);
};
//! \brief A PruneCondition that conjoins two other PruneConditions.
class BinaryPruneCondition final : public PruneCondition {
public:
enum Operator {
AND,
OR,
};
//! \brief Evaluates two sub-conditions according to the specified logical
//! operator.
//!
//! This implements left-to-right evaluation. For Operator::AND, this means
//! if the \a lhs is `false`, the \a rhs will not be consulted. Similarly,
//! with Operator::OR, if the \a lhs is `true`, the \a rhs will not be
//! consulted.
//!
//! \param[in] op The logical operator to apply on \a lhs and \a rhs.
//! \param[in] lhs The left-hand side of \a op. This class takes ownership.
//! \param[in] rhs The right-hand side of \a op. This class takes ownership.
BinaryPruneCondition(Operator op, PruneCondition* lhs, PruneCondition* rhs);
~BinaryPruneCondition();
bool ShouldPruneReport(const CrashReportDatabase::Report& report) override;
private:
const Operator op_;
std::unique_ptr<PruneCondition> lhs_;
std::unique_ptr<PruneCondition> rhs_;
DISALLOW_COPY_AND_ASSIGN(BinaryPruneCondition);
};
} // namespace crashpad
#endif // CRASHPAD_CLIENT_PRUNE_CRASH_REPORTS_H_
+183
View File
@@ -0,0 +1,183 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_CLIENT_SETTINGS_H_
#define CRASHPAD_CLIENT_SETTINGS_H_
#include <time.h>
#include <string>
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/scoped_generic.h"
#include "util/file/file_io.h"
#include "util/misc/initialization_state.h"
#include "util/misc/uuid.h"
namespace crashpad {
namespace internal {
struct ScopedLockedFileHandleTraits {
static FileHandle InvalidValue() { return kInvalidFileHandle; }
static void Free(FileHandle handle);
};
} // namespace internal
//! \brief An interface for accessing and modifying the settings of a
//! CrashReportDatabase.
//!
//! This class must not be instantiated directly, but rather an instance of it
//! should be retrieved via CrashReportDatabase::GetSettings().
class Settings {
public:
explicit Settings(const base::FilePath& file_path);
~Settings();
bool Initialize();
//! \brief Retrieves the immutable identifier for this client, which is used
//! on a server to locate all crash reports from a specific Crashpad
//! database.
//!
//! This is automatically initialized when the database is created.
//!
//! \param[out] client_id The unique client identifier.
//!
//! \return On success, returns `true`, otherwise returns `false` with an
//! error logged.
bool GetClientID(UUID* client_id);
//! \brief Retrieves the users preference for submitting crash reports to a
//! collection server.
//!
//! The default value is `false`.
//!
//! \param[out] enabled Whether crash reports should be uploaded.
//!
//! \return On success, returns `true`, otherwise returns `false` with an
//! error logged.
bool GetUploadsEnabled(bool* enabled);
//! \brief Sets the users preference for submitting crash reports to a
//! collection server.
//!
//! \param[in] enabled Whether crash reports should be uploaded.
//!
//! \return On success, returns `true`, otherwise returns `false` with an
//! error logged.
bool SetUploadsEnabled(bool enabled);
//! \brief Retrieves the last time at which a report was attempted to be
//! uploaded.
//!
//! The default value is `0` if it has never been set before.
//!
//! \param[out] time The last time at which a report was uploaded.
//!
//! \return On success, returns `true`, otherwise returns `false` with an
//! error logged.
bool GetLastUploadAttemptTime(time_t* time);
//! \brief Sets the last time at which a report was attempted to be uploaded.
//!
//! This is only meant to be used internally by the CrashReportDatabase.
//!
//! \param[in] time The last time at which a report was uploaded.
//!
//! \return On success, returns `true`, otherwise returns `false` with an
//! error logged.
bool SetLastUploadAttemptTime(time_t time);
private:
struct Data;
// This must be constructed with MakeScopedLockedFileHandle(). It both unlocks
// and closes the file on destruction.
using ScopedLockedFileHandle =
base::ScopedGeneric<FileHandle, internal::ScopedLockedFileHandleTraits>;
static ScopedLockedFileHandle MakeScopedLockedFileHandle(FileHandle file,
FileLocking locking);
// Opens the settings file for reading. On error, logs a message and returns
// the invalid handle.
ScopedLockedFileHandle OpenForReading();
// Opens the settings file for reading and writing. On error, logs a message
// and returns the invalid handle. |mode| determines how the file will be
// opened. |mode| must not be FileWriteMode::kTruncateOrCreate.
//
// If |log_open_error| is false, nothing will be logged for an error
// encountered when attempting to open the file, but this method will still
// return false. This is intended to be used to suppress error messages when
// attempting to create a new settings file when multiple attempts are made.
ScopedLockedFileHandle OpenForReadingAndWriting(FileWriteMode mode,
bool log_open_error);
// Opens the settings file and reads the data. If that fails, an error will
// be logged and the settings will be recovered and re-initialized. If that
// also fails, returns false with additional log data from recovery.
bool OpenAndReadSettings(Data* out_data);
// Opens the settings file for writing and reads the data. If reading fails,
// recovery is attempted. Returns the opened file handle on success, or the
// invalid file handle on failure, with an error logged.
ScopedLockedFileHandle OpenForWritingAndReadSettings(Data* out_data);
// Reads the settings from |handle|. Logs an error and returns false on
// failure. This does not perform recovery.
//
// |handle| must be the result of OpenForReading() or
// OpenForReadingAndWriting().
//
// If |log_read_error| is false, nothing will be logged for a read error, but
// this method will still return false. This is intended to be used to
// suppress error messages when attempting to read a newly created settings
// file.
bool ReadSettings(FileHandle handle, Data* out_data, bool log_read_error);
// Writes the settings to |handle|. Logs an error and returns false on
// failure. This does not perform recovery.
//
// |handle| must be the result of OpenForReadingAndWriting().
bool WriteSettings(FileHandle handle, const Data& data);
// Recovers the settings file by re-initializing the data. If |handle| is the
// invalid handle, this will open the file; if it is not, then it must be the
// result of OpenForReadingAndWriting(). If the invalid handle is passed, the
// caller must not be holding the handle. The new settings data are stored in
// |out_data|. Returns true on success and false on failure, with an error
// logged.
bool RecoverSettings(FileHandle handle, Data* out_data);
// Initializes a settings file and writes the data to |handle|. Returns true
// on success and false on failure, with an error logged.
//
// |handle| must be the result of OpenForReadingAndWriting().
bool InitializeSettings(FileHandle handle);
const base::FilePath& file_path() const { return file_path_; }
base::FilePath file_path_;
InitializationState initialized_;
DISALLOW_COPY_AND_ASSIGN(Settings);
};
} // namespace crashpad
#endif // CRASHPAD_CLIENT_SETTINGS_H_
@@ -0,0 +1,198 @@
// Copyright 2016 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_CLIENT_SIMPLE_ADDRESS_RANGE_BAG_H_
#define CRASHPAD_CLIENT_SIMPLE_ADDRESS_RANGE_BAG_H_
#include <stdint.h>
#include <type_traits>
#include "base/logging.h"
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "util/misc/from_pointer_cast.h"
#include "util/numeric/checked_range.h"
namespace crashpad {
//! \brief A bag implementation using a fixed amount of storage, so that it does
//! not perform any dynamic allocations for its operations.
//!
//! The actual bag storage (TSimpleAddressRangeBag::Entry) is POD, so that it
//! can be transmitted over various IPC mechanisms.
template <size_t NumEntries = 64>
class TSimpleAddressRangeBag {
public:
//! Constant and publicly accessible version of the template parameter.
static const size_t num_entries = NumEntries;
//! \brief A single entry in the bag.
struct Entry {
//! \brief The base address of the range.
uint64_t base;
//! \brief The size of the range in bytes.
uint64_t size;
//! \brief Returns the validity of the entry.
//!
//! If #base and #size are both zero, the entry is considered inactive, and
//! this method returns `false`. Otherwise, returns `true`.
bool is_active() const {
return base != 0 || size != 0;
}
};
//! \brief An iterator to traverse all of the active entries in a
//! TSimpleAddressRangeBag.
class Iterator {
public:
explicit Iterator(const TSimpleAddressRangeBag& bag)
: bag_(bag),
current_(0) {
}
//! \brief Returns the next entry in the bag, or `nullptr` if at the end of
//! the collection.
const Entry* Next() {
while (current_ < bag_.num_entries) {
const Entry* entry = &bag_.entries_[current_++];
if (entry->is_active()) {
return entry;
}
}
return nullptr;
}
private:
const TSimpleAddressRangeBag& bag_;
size_t current_;
DISALLOW_COPY_AND_ASSIGN(Iterator);
};
TSimpleAddressRangeBag()
: entries_() {
}
TSimpleAddressRangeBag(const TSimpleAddressRangeBag& other) {
*this = other;
}
TSimpleAddressRangeBag& operator=(const TSimpleAddressRangeBag& other) {
memcpy(entries_, other.entries_, sizeof(entries_));
return *this;
}
//! \brief Returns the number of active entries. The upper limit for this is
//! \a NumEntries.
size_t GetCount() const {
size_t count = 0;
for (size_t i = 0; i < num_entries; ++i) {
if (entries_[i].is_active()) {
++count;
}
}
return count;
}
//! \brief Inserts the given range into the bag. Duplicates and overlapping
//! ranges are supported and allowed, but not coalesced.
//!
//! \param[in] range The range to be inserted. The range must have either a
//! non-zero base address or size.
//!
//! \return `true` if there was space to insert the range into the bag,
//! otherwise `false` with an error logged.
bool Insert(CheckedRange<uint64_t> range) {
DCHECK(range.base() != 0 || range.size() != 0);
for (size_t i = 0; i < num_entries; ++i) {
if (!entries_[i].is_active()) {
entries_[i].base = range.base();
entries_[i].size = range.size();
return true;
}
}
LOG(ERROR) << "no space available to insert range";
return false;
}
//! \brief Inserts the given range into the bag. Duplicates and overlapping
//! ranges are supported and allowed, but not coalesced.
//!
//! \param[in] base The base of the range to be inserted. May not be null.
//! \param[in] size The size of the range to be inserted. May not be zero.
//!
//! \return `true` if there was space to insert the range into the bag,
//! otherwise `false` with an error logged.
bool Insert(void* base, size_t size) {
DCHECK(base != nullptr);
DCHECK_NE(0u, size);
return Insert(CheckedRange<uint64_t>(FromPointerCast<uint64_t>(base),
base::checked_cast<uint64_t>(size)));
}
//! \brief Removes the given range from the bag.
//!
//! \param[in] range The range to be removed. The range must have either a
//! non-zero base address or size.
//!
//! \return `true` if the range was found and removed, otherwise `false` with
//! an error logged.
bool Remove(CheckedRange<uint64_t> range) {
DCHECK(range.base() != 0 || range.size() != 0);
for (size_t i = 0; i < num_entries; ++i) {
if (entries_[i].base == range.base() &&
entries_[i].size == range.size()) {
entries_[i].base = entries_[i].size = 0;
return true;
}
}
LOG(ERROR) << "did not find range to remove";
return false;
}
//! \brief Removes the given range from the bag.
//!
//! \param[in] base The base of the range to be removed. May not be null.
//! \param[in] size The size of the range to be removed. May not be zero.
//!
//! \return `true` if the range was found and removed, otherwise `false` with
//! an error logged.
bool Remove(void* base, size_t size) {
DCHECK(base != nullptr);
DCHECK_NE(0u, size);
return Remove(CheckedRange<uint64_t>(FromPointerCast<uint64_t>(base),
base::checked_cast<uint64_t>(size)));
}
private:
Entry entries_[NumEntries];
};
//! \brief A TSimpleAddressRangeBag with default template parameters.
using SimpleAddressRangeBag = TSimpleAddressRangeBag<64>;
static_assert(std::is_standard_layout<SimpleAddressRangeBag>::value,
"SimpleAddressRangeBag must be standard layout");
} // namespace crashpad
#endif // CRASHPAD_CLIENT_SIMPLE_ADDRESS_RANGE_BAG_H_
@@ -0,0 +1,288 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_CLIENT_SIMPLE_STRING_DICTIONARY_H_
#define CRASHPAD_CLIENT_SIMPLE_STRING_DICTIONARY_H_
#include <string.h>
#include <sys/types.h>
#include <algorithm>
#include <type_traits>
#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "util/misc/implicit_cast.h"
namespace crashpad {
//! \brief A map/dictionary collection implementation using a fixed amount of
//! storage, so that it does not perform any dynamic allocations for its
//! operations.
//!
//! The actual map storage (TSimpleStringDictionary::Entry) is guaranteed to be
//! POD, so that it can be transmitted over various IPC mechanisms.
//!
//! The template parameters control the amount of storage used for the key,
//! value, and map. The \a KeySize and \a ValueSize are measured in bytes, not
//! glyphs, and include space for a trailing `NUL` byte. This gives space for
//! `KeySize - 1` and `ValueSize - 1` characters in an entry. \a NumEntries is
//! the total number of entries that will fit in the map.
template <size_t KeySize = 256, size_t ValueSize = 256, size_t NumEntries = 64>
class TSimpleStringDictionary {
public:
//! \brief Constant and publicly accessible versions of the template
//! parameters.
//! \{
static const size_t key_size = KeySize;
static const size_t value_size = ValueSize;
static const size_t num_entries = NumEntries;
//! \}
//! \brief A single entry in the map.
struct Entry {
//! \brief The entrys key.
//!
//! This string is always `NUL`-terminated. If this is a 0-length
//! `NUL`-terminated string, the entry is inactive.
char key[KeySize];
//! \brief The entrys value.
//!
//! This string is always `NUL`-terminated.
char value[ValueSize];
//! \brief Returns the validity of the entry.
//!
//! If #key is an empty string, the entry is considered inactive, and this
//! method returns `false`. Otherwise, returns `true`.
bool is_active() const {
return key[0] != '\0';
}
};
//! \brief An iterator to traverse all of the active entries in a
//! TSimpleStringDictionary.
class Iterator {
public:
explicit Iterator(const TSimpleStringDictionary& map)
: map_(map),
current_(0) {
}
//! \brief Returns the next entry in the map, or `nullptr` if at the end of
//! the collection.
const Entry* Next() {
while (current_ < map_.num_entries) {
const Entry* entry = &map_.entries_[current_++];
if (entry->is_active()) {
return entry;
}
}
return nullptr;
}
private:
const TSimpleStringDictionary& map_;
size_t current_;
DISALLOW_COPY_AND_ASSIGN(Iterator);
};
TSimpleStringDictionary()
: entries_() {
}
TSimpleStringDictionary(const TSimpleStringDictionary& other) {
*this = other;
}
TSimpleStringDictionary& operator=(const TSimpleStringDictionary& other) {
memcpy(entries_, other.entries_, sizeof(entries_));
return *this;
}
//! \brief Returns the number of active key/value pairs. The upper limit for
//! this is \a NumEntries.
size_t GetCount() const {
size_t count = 0;
for (size_t i = 0; i < num_entries; ++i) {
if (entries_[i].is_active()) {
++count;
}
}
return count;
}
//! \brief Given \a key, returns its corresponding value.
//!
//! \param[in] key The key to look up. This must not be `nullptr`, nor an
//! empty string. It must not contain embedded `NUL`s.
//!
//! \return The corresponding value for \a key, or if \a key is not found,
//! `nullptr`.
const char* GetValueForKey(base::StringPiece key) const {
DCHECK(key.data());
DCHECK(key.size());
DCHECK_EQ(key.find('\0', 0), base::StringPiece::npos);
if (!key.data() || !key.size()) {
return nullptr;
}
const Entry* entry = GetConstEntryForKey(key);
if (!entry) {
return nullptr;
}
return entry->value;
}
//! \brief Stores \a value into \a key, replacing the existing value if \a key
//! is already present.
//!
//! If \a key is not yet in the map and the map is already full (containing
//! \a NumEntries active entries), this operation silently fails.
//!
//! \param[in] key The key to store. This must not be `nullptr`, nor an empty
//! string. It must not contain embedded `NUL`s.
//! \param[in] value The value to store. If `nullptr`, \a key is removed from
//! the map. Must not contain embedded `NUL`s.
void SetKeyValue(base::StringPiece key, base::StringPiece value) {
if (!value.data()) {
RemoveKey(key);
return;
}
DCHECK(key.data());
DCHECK(key.size());
DCHECK_EQ(key.find('\0', 0), base::StringPiece::npos);
if (!key.data() || !key.size()) {
return;
}
// |key| must not be an empty string.
DCHECK_NE(key[0], '\0');
if (key[0] == '\0') {
return;
}
// |value| must not contain embedded NULs.
DCHECK_EQ(value.find('\0', 0), base::StringPiece::npos);
Entry* entry = GetEntryForKey(key);
// If it does not yet exist, attempt to insert it.
if (!entry) {
for (size_t i = 0; i < num_entries; ++i) {
if (!entries_[i].is_active()) {
entry = &entries_[i];
SetFromStringPiece(key, entry->key, key_size);
break;
}
}
}
// If the map is out of space, |entry| will be nullptr.
if (!entry) {
return;
}
#ifndef NDEBUG
// Sanity check that the key only appears once.
int count = 0;
for (size_t i = 0; i < num_entries; ++i) {
if (EntryKeyEquals(key, entries_[i])) {
++count;
}
}
DCHECK_EQ(count, 1);
#endif
SetFromStringPiece(value, entry->value, value_size);
}
//! \brief Removes \a key from the map.
//!
//! If \a key is not found, this is a no-op.
//!
//! \param[in] key The key of the entry to remove. This must not be `nullptr`,
//! nor an empty string. It must not contain embedded `NUL`s.
void RemoveKey(base::StringPiece key) {
DCHECK(key.data());
DCHECK(key.size());
DCHECK_EQ(key.find('\0', 0), base::StringPiece::npos);
if (!key.data() || !key.size()) {
return;
}
Entry* entry = GetEntryForKey(key);
if (entry) {
entry->key[0] = '\0';
entry->value[0] = '\0';
}
DCHECK_EQ(GetEntryForKey(key), implicit_cast<Entry*>(nullptr));
}
private:
static void SetFromStringPiece(base::StringPiece src,
char* dst,
size_t dst_size) {
size_t copy_len = std::min(dst_size - 1, src.size());
src.copy(dst, copy_len);
dst[copy_len] = '\0';
}
static bool EntryKeyEquals(base::StringPiece key, const Entry& entry) {
if (key.size() >= KeySize)
return false;
// Test for a NUL terminator and early out if it's absent.
if (entry.key[key.size()] != '\0')
return false;
// As there's a NUL terminator at the right position in the entries
// string, strncmp can do the rest.
return strncmp(key.data(), entry.key, key.size()) == 0;
}
const Entry* GetConstEntryForKey(base::StringPiece key) const {
for (size_t i = 0; i < num_entries; ++i) {
if (EntryKeyEquals(key, entries_[i])) {
return &entries_[i];
}
}
return nullptr;
}
Entry* GetEntryForKey(base::StringPiece key) {
return const_cast<Entry*>(GetConstEntryForKey(key));
}
Entry entries_[NumEntries];
};
//! \brief A TSimpleStringDictionary with default template parameters.
//!
//! For historical reasons this specialized version is available with the same
//! size factors as a previous implementation.
using SimpleStringDictionary = TSimpleStringDictionary<256, 256, 64>;
static_assert(std::is_standard_layout<SimpleStringDictionary>::value,
"SimpleStringDictionary must be standard layout");
} // namespace crashpad
#endif // CRASHPAD_CLIENT_SIMPLE_STRING_DICTIONARY_H_
@@ -0,0 +1,26 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_CLIENT_SIMULATE_CRASH_H_
#define CRASHPAD_CLIENT_SIMULATE_CRASH_H_
#include "build/build_config.h"
#if defined(OS_MACOSX)
#include "client/simulate_crash_mac.h"
#elif defined(OS_WIN)
#include "client/simulate_crash_win.h"
#endif
#endif // CRASHPAD_CLIENT_SIMULATE_CRASH_H_
@@ -0,0 +1,60 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_CLIENT_SIMULATE_CRASH_MAC_H_
#define CRASHPAD_CLIENT_SIMULATE_CRASH_MAC_H_
#include <mach/mach.h>
#include "client/capture_context_mac.h"
//! \file
namespace crashpad {
//! \brief Simulates a exception without crashing.
//!
//! This function searches for an `EXC_CRASH` handler in the same manner that
//! the kernel does, and sends it an exception message to that handler in the
//! format that the handler expects, considering the behavior and thread state
//! flavor that are registered for it. The exception sent to the handler will be
//! ::kMachExceptionSimulated, not `EXC_CRASH`.
//!
//! Typically, the CRASHPAD_SIMULATE_CRASH() macro will be used in preference to
//! this function, because it combines the context-capture operation with the
//! raising of a simulated exception.
//!
//! This function returns normally after the exception message is processed. If
//! no valid handler was found, or no handler processed the exception
//! successfully, a warning will be logged, but these conditions are not
//! considered fatal.
//!
//! \param[in] cpu_context The thread state to pass to the exception handler as
//! the exception context, provided that it is compatible with the thread
//! state flavor that the exception handler accepts. If it is not
//! compatible, the correct thread state for the handler will be obtained by
//! calling `thread_get_state()`.
void SimulateCrash(const NativeCPUContext& cpu_context);
} // namespace crashpad
//! \brief Captures the CPU context and simulates an exception without crashing.
#define CRASHPAD_SIMULATE_CRASH() \
do { \
crashpad::NativeCPUContext cpu_context; \
crashpad::CaptureContext(&cpu_context); \
crashpad::SimulateCrash(cpu_context); \
} while (false)
#endif // CRASHPAD_CLIENT_SIMULATE_CRASH_MAC_H_
@@ -0,0 +1,33 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_CLIENT_SIMULATE_CRASH_WIN_H_
#define CRASHPAD_CLIENT_SIMULATE_CRASH_WIN_H_
#include <windows.h>
#include "client/crashpad_client.h"
#include "util/win/capture_context.h"
//! \file
//! \brief Captures the CPU context and captures a dump without an exception.
#define CRASHPAD_SIMULATE_CRASH() \
do { \
CONTEXT context; \
crashpad::CaptureContext(&context); \
crashpad::CrashpadClient::DumpWithoutCrash(context); \
} while (false)
#endif // CRASHPAD_CLIENT_SIMULATE_CRASH_WIN_H_
@@ -0,0 +1,35 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_ANDROID_DLFCN_INTERNAL_H_
#define CRASHPAD_COMPAT_ANDROID_DLFCN_INTERNAL_H_
namespace crashpad {
namespace internal {
//! \brief Provide a wrapper for `dlsym`.
//!
//! dlsym on Android KitKat (4.4.*) raises SIGFPE when searching for a
//! non-existent symbol. This wrapper avoids crashing in this circumstance.
//! https://code.google.com/p/android/issues/detail?id=61799
//!
//! The parameters and return value for this function are the same as for
//! `dlsym`, but a return value for `dlerror` may not be set in the event of an
//! error.
void* Dlsym(void* handle, const char* symbol);
} // namespace internal
} // namespace crashpad
#endif // CRASHPAD_COMPAT_ANDROID_DLFCN_INTERNAL_H_
@@ -0,0 +1,58 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_ANDROID_ELF_H_
#define CRASHPAD_COMPAT_ANDROID_ELF_H_
#include_next <elf.h>
#include <android/api-level.h>
#if !defined(ELF32_ST_VISIBILITY)
#define ELF32_ST_VISIBILITY(other) ((other) & 0x3)
#endif
#if !defined(ELF64_ST_VISIBILITY)
#define ELF64_ST_VISIBILITY(other) ELF32_ST_VISIBILITY(other)
#endif
// Android 5.0.0 (API 21) NDK
#if !defined(STT_COMMON)
#define STT_COMMON 5
#endif
#if !defined(STT_TLS)
#define STT_TLS 6
#endif
// ELF note header types are normally provided by <linux/elf.h>. While unified
// headers include <linux/elf.h> in <elf.h>, traditional headers do not, prior
// to API 21. <elf.h> and <linux/elf.h> can't both be included in the same
// translation unit due to collisions, so we provide these types here.
#if __ANDROID_API__ < 21 && !defined(__ANDROID_API_N__)
typedef struct {
Elf32_Word n_namesz;
Elf32_Word n_descsz;
Elf32_Word n_type;
} Elf32_Nhdr;
typedef struct {
Elf64_Word n_namesz;
Elf64_Word n_descsz;
Elf64_Word n_type;
} Elf64_Nhdr;
#endif // __ANDROID_API__ < 21 && !defined(NT_PRSTATUS)
#endif // CRASHPAD_COMPAT_ANDROID_ELF_H_
@@ -0,0 +1,38 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_ANDROID_LINUX_ELF_H_
#define CRASHPAD_COMPAT_ANDROID_LINUX_ELF_H_
#include_next <linux/elf.h>
// Android 5.0.0 (API 21) NDK
#if defined(__i386__) || defined(__x86_64__)
#if !defined(NT_386_TLS)
#define NT_386_TLS 0x200
#endif
#endif // __i386__ || __x86_64__
#if defined(__ARMEL__) || defined(__aarch64__)
#if !defined(NT_ARM_VFP)
#define NT_ARM_VFP 0x400
#endif
#if !defined(NT_ARM_TLS)
#define NT_ARM_TLS 0x401
#endif
#endif // __ARMEL__ || __aarch64__
#endif // CRASHPAD_COMPAT_ANDROID_LINUX_ELF_H_
@@ -0,0 +1,25 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_ANDROID_LINUX_PRCTL_H_
#define CRASHPAD_COMPAT_ANDROID_LINUX_PRCTL_H_
#include_next <linux/prctl.h>
// Android 5.0.0 (API 21) NDK
#if !defined(PR_SET_PTRACER)
#define PR_SET_PTRACER 0x59616d61
#endif
#endif // CRASHPAD_COMPAT_ANDROID_LINUX_PRCTL_H_
@@ -0,0 +1,25 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_ANDROID_LINUX_PTRACE_H_
#define CRASHPAD_COMPAT_ANDROID_LINUX_PTRACE_H_
#include_next <linux/ptrace.h>
// Android 5.0.0 (API 21) NDK
#if !defined(PTRACE_GETREGSET)
#define PTRACE_GETREGSET 0x4204
#endif
#endif // CRASHPAD_COMPAT_ANDROID_LINUX_PTRACE_H_
@@ -0,0 +1,30 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_ANDROID_SCHED_H_
#define CRASHPAD_COMPAT_ANDROID_SCHED_H_
#include_next <sched.h>
// Android 5.0.0 (API 21) NDK
#if !defined(SCHED_BATCH)
#define SCHED_BATCH 3
#endif
#if !defined(SCHED_IDLE)
#define SCHED_IDLE 5
#endif
#endif // CRASHPAD_COMPAT_ANDROID_SCHED_H_
@@ -0,0 +1,50 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_ANDROID_SYS_EPOLL_H_
#define CRASHPAD_COMPAT_ANDROID_SYS_EPOLL_H_
#include_next <sys/epoll.h>
#include <android/api-level.h>
#include <fcntl.h>
// This is missing from traditional headers before API 21.
#if !defined(EPOLLRDHUP)
#define EPOLLRDHUP 0x00002000
#endif
// EPOLL_CLOEXEC is undefined in traditional headers before API 21 and removed
// from unified headers at API levels < 21 as a means to indicate that
// epoll_create1 is missing from the C library, but the raw system call should
// still be available.
#if !defined(EPOLL_CLOEXEC)
#define EPOLL_CLOEXEC O_CLOEXEC
#endif
#if __ANDROID_API__ < 21
#ifdef __cplusplus
extern "C" {
#endif
int epoll_create1(int flags);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __ANDROID_API__ < 21
#endif // CRASHPAD_COMPAT_ANDROID_SYS_EPOLL_H_
@@ -0,0 +1,43 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_ANDROID_SYS_MMAN_H_
#define CRASHPAD_COMPAT_ANDROID_SYS_MMAN_H_
#include_next <sys/mman.h>
#include <android/api-level.h>
#include <sys/cdefs.h>
// Theres no mmap() wrapper compatible with a 64-bit off_t for 32-bit code
// until API 21 (Android 5.0/“Lollipop”). A custom mmap() wrapper is provided
// here. Note that this scenario is only possible with NDK unified headers.
//
// https://android.googlesource.com/platform/bionic/+/0bfcbaf4d069e005d6e959d97f8d11c77722b70d/docs/32-bit-abi.md#is-32_bit-1
#if defined(__USE_FILE_OFFSET64) && __ANDROID_API__ < 21
#ifdef __cplusplus
extern "C" {
#endif
void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // defined(__USE_FILE_OFFSET64) && __ANDROID_API__ < 21
#endif // CRASHPAD_COMPAT_ANDROID_SYS_MMAN_H_
@@ -0,0 +1,42 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_ANDROID_SYS_SYSCALL_H_
#define CRASHPAD_COMPAT_ANDROID_SYS_SYSCALL_H_
#include_next <sys/syscall.h>
// Android 5.0.0 (API 21) NDK
#if !defined(SYS_epoll_create1)
#define SYS_epoll_create1 __NR_epoll_create1
#endif
#if !defined(SYS_gettid)
#define SYS_gettid __NR_gettid
#endif
#if !defined(SYS_timer_create)
#define SYS_timer_create __NR_timer_create
#endif
#if !defined(SYS_timer_getoverrun)
#define SYS_timer_getoverrun __NR_timer_getoverrun
#endif
#if !defined(SYS_timer_settime)
#define SYS_timer_settime __NR_timer_settime
#endif
#endif // CRASHPAD_COMPAT_ANDROID_SYS_SYSCALL_H_
@@ -0,0 +1,23 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_ANDROID_SYS_USER_H_
#define CRASHPAD_COMPAT_ANDROID_SYS_USER_H_
// This is needed for traditional headers.
#include <sys/types.h>
#include_next <sys/user.h>
#endif // CRASHPAD_COMPAT_ANDROID_SYS_USER_H_
@@ -0,0 +1,27 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_LINUX_SIGNAL_H_
#define CRASHPAD_COMPAT_LINUX_SIGNAL_H_
#include_next <signal.h>
// Missing from glibc and bionic-x86_64
#if defined(__x86_64__) || defined(__i386__)
#if !defined(X86_FXSR_MAGIC)
#define X86_FXSR_MAGIC 0x0000
#endif
#endif // __x86_64__ || __i386__
#endif // CRASHPAD_COMPAT_LINUX_SIGNAL_H_
@@ -0,0 +1,30 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_LINUX_SYS_PTRACE_H_
#define CRASHPAD_COMPAT_LINUX_SYS_PTRACE_H_
#include_next <sys/ptrace.h>
#include <sys/cdefs.h>
// https://sourceware.org/bugzilla/show_bug.cgi?id=22433
#if !defined(PTRACE_GET_THREAD_AREA) && \
defined(__GLIBC__) && (defined(__i386__) || defined(__x86_64__))
static constexpr __ptrace_request PTRACE_GET_THREAD_AREA =
static_cast<__ptrace_request>(25);
#define PTRACE_GET_THREAD_AREA PTRACE_GET_THREAD_AREA
#endif // !PTRACE_GET_THREAD_AREA && __GLIBC__ && (__i386__ || __x86_64__)
#endif // CRASHPAD_COMPAT_LINUX_SYS_PTRACE_H_
@@ -0,0 +1,62 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_MAC_AVAILABILITYMACROS_H_
#define CRASHPAD_COMPAT_MAC_AVAILABILITYMACROS_H_
#include_next <AvailabilityMacros.h>
// 10.7 SDK
#ifndef MAC_OS_X_VERSION_10_7
#define MAC_OS_X_VERSION_10_7 1070
#endif
// 10.8 SDK
#ifndef MAC_OS_X_VERSION_10_8
#define MAC_OS_X_VERSION_10_8 1080
#endif
// 10.9 SDK
#ifndef MAC_OS_X_VERSION_10_9
#define MAC_OS_X_VERSION_10_9 1090
#endif
// 10.10 SDK
#ifndef MAC_OS_X_VERSION_10_10
#define MAC_OS_X_VERSION_10_10 101000
#endif
// 10.11 SDK
#ifndef MAC_OS_X_VERSION_10_11
#define MAC_OS_X_VERSION_10_11 101100
#endif
// 10.12 SDK
#ifndef MAC_OS_X_VERSION_10_12
#define MAC_OS_X_VERSION_10_12 101200
#endif
// 10.13 SDK
#ifndef MAC_OS_X_VERSION_10_13
#define MAC_OS_X_VERSION_10_13 101300
#endif
#endif // CRASHPAD_COMPAT_MAC_AVAILABILITYMACROS_H_
@@ -0,0 +1,76 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_MAC_KERN_EXC_RESOURCE_H_
#define CRASHPAD_COMPAT_MAC_KERN_EXC_RESOURCE_H_
#if __has_include_next(<kern/exc_resource.h>)
#include_next <kern/exc_resource.h>
#endif
// 10.9 SDK
#ifndef EXC_RESOURCE_DECODE_RESOURCE_TYPE
#define EXC_RESOURCE_DECODE_RESOURCE_TYPE(code) (((code) >> 61) & 0x7ull)
#endif
#ifndef EXC_RESOURCE_DECODE_FLAVOR
#define EXC_RESOURCE_DECODE_FLAVOR(code) (((code) >> 58) & 0x7ull)
#endif
#ifndef RESOURCE_TYPE_CPU
#define RESOURCE_TYPE_CPU 1
#endif
#ifndef RESOURCE_TYPE_WAKEUPS
#define RESOURCE_TYPE_WAKEUPS 2
#endif
#ifndef RESOURCE_TYPE_MEMORY
#define RESOURCE_TYPE_MEMORY 3
#endif
#ifndef FLAVOR_CPU_MONITOR
#define FLAVOR_CPU_MONITOR 1
#endif
#ifndef FLAVOR_WAKEUPS_MONITOR
#define FLAVOR_WAKEUPS_MONITOR 1
#endif
#ifndef FLAVOR_HIGH_WATERMARK
#define FLAVOR_HIGH_WATERMARK 1
#endif
// 10.10 SDK
#ifndef FLAVOR_CPU_MONITOR_FATAL
#define FLAVOR_CPU_MONITOR_FATAL 2
#endif
// 10.12 SDK
#ifndef RESOURCE_TYPE_IO
#define RESOURCE_TYPE_IO 4
#endif
#ifndef FLAVOR_IO_PHYSICAL_WRITES
#define FLAVOR_IO_PHYSICAL_WRITES 1
#endif
#ifndef FLAVOR_IO_LOGICAL_WRITES
#define FLAVOR_IO_LOGICAL_WRITES 2
#endif
#endif // CRASHPAD_COMPAT_MAC_KERN_EXC_RESOURCE_H_
@@ -0,0 +1,32 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_MAC_MACH_O_LOADER_H_
#define CRASHPAD_COMPAT_MAC_MACH_O_LOADER_H_
#include_next <mach-o/loader.h>
// 10.7 SDK
#ifndef S_THREAD_LOCAL_ZEROFILL
#define S_THREAD_LOCAL_ZEROFILL 0x12
#endif
// 10.8 SDK
#ifndef LC_SOURCE_VERSION
#define LC_SOURCE_VERSION 0x2a
#endif
#endif // CRASHPAD_COMPAT_MAC_MACH_O_LOADER_H_
@@ -0,0 +1,28 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_MAC_MACH_I386_THREAD_STATE_H_
#define CRASHPAD_COMPAT_MAC_MACH_I386_THREAD_STATE_H_
#include_next <mach/i386/thread_state.h>
// 10.13 SDK
//
// This was defined as 244 in the 10.7 through 10.12 SDKs, and 144 previously.
#if I386_THREAD_STATE_MAX < 614
#undef I386_THREAD_STATE_MAX
#define I386_THREAD_STATE_MAX (614)
#endif
#endif // CRASHPAD_COMPAT_MAC_MACH_I386_THREAD_STATE_H_
@@ -0,0 +1,120 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_MAC_MACH_MACH_H_
#define CRASHPAD_COMPAT_MAC_MACH_MACH_H_
#include_next <mach/mach.h>
// <mach/exception_types.h>
// 10.8 SDK
#ifndef EXC_RESOURCE
#define EXC_RESOURCE 11
#endif
#ifndef EXC_MASK_RESOURCE
#define EXC_MASK_RESOURCE (1 << EXC_RESOURCE)
#endif
// 10.9 SDK
#ifndef EXC_GUARD
#define EXC_GUARD 12
#endif
#ifndef EXC_MASK_GUARD
#define EXC_MASK_GUARD (1 << EXC_GUARD)
#endif
// 10.11 SDK
#ifndef EXC_CORPSE_NOTIFY
#define EXC_CORPSE_NOTIFY 13
#endif
#ifndef EXC_MASK_CORPSE_NOTIFY
#define EXC_MASK_CORPSE_NOTIFY (1 << EXC_CORPSE_NOTIFY)
#endif
// Dont expose EXC_MASK_ALL at all, because its definition varies with SDK, and
// older kernels will reject values that they dont understand. Instead, use
// crashpad::ExcMaskAll(), which computes the correct value of EXC_MASK_ALL for
// the running system.
#undef EXC_MASK_ALL
#if defined(__i386__) || defined(__x86_64__)
// <mach/i386/exception.h>
// 10.11 SDK
#if EXC_TYPES_COUNT > 14 // Definition varies with SDK
#error Update this file for new exception types
#elif EXC_TYPES_COUNT != 14
#undef EXC_TYPES_COUNT
#define EXC_TYPES_COUNT 14
#endif
// <mach/i386/thread_status.h>
// 10.6 SDK
//
// Earlier versions of this SDK didnt have AVX definitions. They didnt appear
// until the version of the 10.6 SDK that shipped with Xcode 4.2, although
// versions of this SDK appeared with Xcode releases as early as Xcode 3.2.
// Similarly, the kernel didnt handle AVX state until Mac OS X 10.6.8
// (xnu-1504.15.3) and presumably the hardware-specific versions of Mac OS X
// 10.6.7 intended to run on processors with AVX.
#ifndef x86_AVX_STATE32
#define x86_AVX_STATE32 16
#endif
#ifndef x86_AVX_STATE64
#define x86_AVX_STATE64 17
#endif
// 10.8 SDK
#ifndef x86_AVX_STATE
#define x86_AVX_STATE 18
#endif
// 10.13 SDK
#ifndef x86_AVX512_STATE32
#define x86_AVX512_STATE32 19
#endif
#ifndef x86_AVX512_STATE64
#define x86_AVX512_STATE64 20
#endif
#ifndef x86_AVX512_STATE
#define x86_AVX512_STATE 21
#endif
#endif // defined(__i386__) || defined(__x86_64__)
// <mach/thread_status.h>
// 10.8 SDK
#ifndef THREAD_STATE_FLAVOR_LIST_10_9
#define THREAD_STATE_FLAVOR_LIST_10_9 129
#endif
#endif // CRASHPAD_COMPAT_MAC_MACH_MACH_H_
@@ -0,0 +1,26 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_MAC_SYS_RESOURCE_H_
#define CRASHPAD_COMPAT_MAC_SYS_RESOURCE_H_
#include_next <sys/resource.h>
// 10.9 SDK
#ifndef WAKEMON_MAKE_FATAL
#define WAKEMON_MAKE_FATAL 0x10
#endif
#endif // CRASHPAD_COMPAT_MAC_SYS_RESOURCE_H_
@@ -0,0 +1,44 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_NON_MAC_MACH_MACH_H_
#define CRASHPAD_COMPAT_NON_MAC_MACH_MACH_H_
//! \file
// <mach/exception_types.h>
//! \anchor EXC_x
//! \name EXC_*
//!
//! \brief Mach exception type definitions.
//! \{
#define EXC_BAD_ACCESS 1
#define EXC_BAD_INSTRUCTION 2
#define EXC_ARITHMETIC 3
#define EXC_EMULATION 4
#define EXC_SOFTWARE 5
#define EXC_BREAKPOINT 6
#define EXC_SYSCALL 7
#define EXC_MACH_SYSCALL 8
#define EXC_RPC_ALERT 9
#define EXC_CRASH 10
#define EXC_RESOURCE 11
#define EXC_GUARD 12
#define EXC_CORPSE_NOTIFY 13
#define EXC_TYPES_COUNT 14
//! \}
#endif // CRASHPAD_COMPAT_NON_MAC_MACH_MACH_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,49 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_NON_WIN_MINWINBASE_H_
#define CRASHPAD_COMPAT_NON_WIN_MINWINBASE_H_
#include <stdint.h>
//! \brief Represents a date and time.
struct SYSTEMTIME {
//! \brief The year, represented fully.
//!
//! The year 2014 would be represented in this field as `2014`.
uint16_t wYear;
//! \brief The month of the year, `1` for January and `12` for December.
uint16_t wMonth;
//! \brief The day of the week, `0` for Sunday and `6` for Saturday.
uint16_t wDayOfWeek;
//! \brief The day of the month, `1` through `31`.
uint16_t wDay;
//! \brief The hour of the day, `0` through `23`.
uint16_t wHour;
//! \brief The minute of the hour, `0` through `59`.
uint16_t wMinute;
//! \brief The second of the minute, `0` through `60`.
uint16_t wSecond;
//! \brief The millisecond of the second, `0` through `999`.
uint16_t wMilliseconds;
};
#endif // CRASHPAD_COMPAT_NON_WIN_MINWINBASE_H_
@@ -0,0 +1,61 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_NON_WIN_TIMEZONEAPI_H_
#define CRASHPAD_COMPAT_NON_WIN_TIMEZONEAPI_H_
#include <stdint.h>
#include "base/strings/string16.h"
#include "compat/non_win/minwinbase.h"
//! \brief Information about a time zone and its daylight saving rules.
struct TIME_ZONE_INFORMATION {
//! \brief The number of minutes west of UTC.
int32_t Bias;
//! \brief The UTF-16-encoded name of the time zone when observing standard
//! time.
base::char16 StandardName[32];
//! \brief The date and time to switch from daylight saving time to standard
//! time.
//!
//! This can be a specific time, or with SYSTEMTIME::wYear set to `0`, it can
//! reflect an annual recurring transition. In that case, SYSTEMTIME::wDay in
//! the range `1` to `5` is interpreted as the given occurrence of
//! SYSTEMTIME::wDayOfWeek within the month, `1` being the first occurrence
//! and `5` being the last (even if there are fewer than 5).
SYSTEMTIME StandardDate;
//! \brief The bias relative to #Bias to be applied when observing standard
//! time.
int32_t StandardBias;
//! \brief The UTF-16-encoded name of the time zone when observing daylight
//! saving time.
base::char16 DaylightName[32];
//! \brief The date and time to switch from standard time to daylight saving
//! time.
//!
//! This field is specified in the same manner as #StandardDate.
SYSTEMTIME DaylightDate;
//! \brief The bias relative to #Bias to be applied when observing daylight
//! saving time.
int32_t DaylightBias;
};
#endif // CRASHPAD_COMPAT_NON_WIN_TIMEZONEAPI_H_
@@ -0,0 +1,184 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_NON_WIN_VERRSRC_H_
#define CRASHPAD_COMPAT_NON_WIN_VERRSRC_H_
#include <stdint.h>
//! \file
//! \brief The magic number for a VS_FIXEDFILEINFO structure, stored in
//! VS_FIXEDFILEINFO::dwSignature.
#define VS_FFI_SIGNATURE 0xfeef04bd
//! \brief The version of a VS_FIXEDFILEINFO structure, stored in
//! VS_FIXEDFILEINFO::dwStrucVersion.
#define VS_FFI_STRUCVERSION 0x00010000
//! \anchor VS_FF_x
//! \name VS_FF_*
//!
//! \brief File attribute values for VS_FIXEDFILEINFO::dwFileFlags and
//! VS_FIXEDFILEINFO::dwFileFlagsMask.
//! \{
#define VS_FF_DEBUG 0x00000001
#define VS_FF_PRERELEASE 0x00000002
#define VS_FF_PATCHED 0x00000004
#define VS_FF_PRIVATEBUILD 0x00000008
#define VS_FF_INFOINFERRED 0x00000010
#define VS_FF_SPECIALBUILD 0x00000020
//! \}
//! \anchor VOS_x
//! \name VOS_*
//!
//! \brief Operating system values for VS_FIXEDFILEINFO::dwFileOS.
//! \{
#define VOS_UNKNOWN 0x00000000
#define VOS_DOS 0x00010000
#define VOS_OS216 0x00020000
#define VOS_OS232 0x00030000
#define VOS_NT 0x00040000
#define VOS_WINCE 0x00050000
#define VOS__BASE 0x00000000
#define VOS__WINDOWS16 0x00000001
#define VOS__PM16 0x00000002
#define VOS__PM32 0x00000003
#define VOS__WINDOWS32 0x00000004
#define VOS_DOS_WINDOWS16 0x00010001
#define VOS_DOS_WINDOWS32 0x00010004
#define VOS_OS216_PM16 0x00020002
#define VOS_OS232_PM32 0x00030003
#define VOS_NT_WINDOWS32 0x00040004
//! \}
//! \anchor VFT_x
//! \name VFT_*
//!
//! \brief File type values for VS_FIXEDFILEINFO::dwFileType.
//! \{
#define VFT_UNKNOWN 0x00000000
#define VFT_APP 0x00000001
#define VFT_DLL 0x00000002
#define VFT_DRV 0x00000003
#define VFT_FONT 0x00000004
#define VFT_VXD 0x00000005
#define VFT_STATIC_LIB 0x00000007
//! \}
//! \anchor VFT2_x
//! \name VFT2_*
//!
//! \brief File subtype values for VS_FIXEDFILEINFO::dwFileSubtype.
//! \{
#define VFT2_UNKNOWN 0x00000000
#define VFT2_DRV_PRINTER 0x00000001
#define VFT2_DRV_KEYBOARD 0x00000002
#define VFT2_DRV_LANGUAGE 0x00000003
#define VFT2_DRV_DISPLAY 0x00000004
#define VFT2_DRV_MOUSE 0x00000005
#define VFT2_DRV_NETWORK 0x00000006
#define VFT2_DRV_SYSTEM 0x00000007
#define VFT2_DRV_INSTALLABLE 0x00000008
#define VFT2_DRV_SOUND 0x00000009
#define VFT2_DRV_COMM 0x0000000A
#define VFT2_DRV_INPUTMETHOD 0x0000000B
#define VFT2_DRV_VERSIONED_PRINTER 0x0000000C
#define VFT2_FONT_RASTER 0x00000001
#define VFT2_FONT_VECTOR 0x00000002
#define VFT2_FONT_TRUETYPE 0x00000003
//! \}
//! \brief Version information for a file.
//!
//! On Windows, this information is derived from a files version information
//! resource, and is obtained by calling `VerQueryValue()` with an `lpSubBlock`
//! argument of `"\"` (a single backslash).
struct VS_FIXEDFILEINFO {
//! \brief The structures magic number, ::VS_FFI_SIGNATURE.
uint32_t dwSignature;
//! \brief The structures version, ::VS_FFI_STRUCVERSION.
uint32_t dwStrucVersion;
//! \brief The more-significant portion of the files version number.
//!
//! This field contains the first two components of a four-component version
//! number. For a file whose version is 1.2.3.4, this field would be
//! `0x00010002`.
//!
//! \sa dwFileVersionLS
uint32_t dwFileVersionMS;
//! \brief The less-significant portion of the files version number.
//!
//! This field contains the last two components of a four-component version
//! number. For a file whose version is 1.2.3.4, this field would be
//! `0x00030004`.
//!
//! \sa dwFileVersionMS
uint32_t dwFileVersionLS;
//! \brief The more-significant portion of the products version number.
//!
//! This field contains the first two components of a four-component version
//! number. For a product whose version is 1.2.3.4, this field would be
//! `0x00010002`.
//!
//! \sa dwProductVersionLS
uint32_t dwProductVersionMS;
//! \brief The less-significant portion of the products version number.
//!
//! This field contains the last two components of a four-component version
//! number. For a product whose version is 1.2.3.4, this field would be
//! `0x00030004`.
//!
//! \sa dwProductVersionMS
uint32_t dwProductVersionLS;
//! \brief A bitmask of \ref VS_FF_x "VS_FF_*" values indicating which bits in
//! #dwFileFlags are valid.
uint32_t dwFileFlagsMask;
//! \brief A bitmask of \ref VS_FF_x "VS_FF_*" values identifying attributes
//! of the file. Only bits present in #dwFileFlagsMask are valid.
uint32_t dwFileFlags;
//! \brief The files intended operating system, a value of \ref VOS_x
//! "VOS_*".
uint32_t dwFileOS;
//! \brief The files type, a value of \ref VFT_x "VFT_*".
uint32_t dwFileType;
//! \brief The files subtype, a value of \ref VFT2_x "VFT2_*" corresponding
//! to its #dwFileType, if the file type has subtypes.
uint32_t dwFileSubtype;
//! \brief The more-significant portion of the files creation date.
//!
//! The intended encoding of this field is unknown. This field is unused and
//! always has the value `0`.
uint32_t dwFileDateMS;
//! \brief The less-significant portion of the files creation date.
//!
//! The intended encoding of this field is unknown. This field is unused and
//! always has the value `0`.
uint32_t dwFileDateLS;
};
#endif // CRASHPAD_COMPAT_NON_WIN_VERRSRC_H_
@@ -0,0 +1,17 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// dbghelp.h on Windows requires inclusion of windows.h before it. To avoid
// cluttering all inclusions of dbghelp.h with #ifdefs, always include windows.h
// and have an empty one on non-Windows platforms.
@@ -0,0 +1,250 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_NON_WIN_WINNT_H_
#define CRASHPAD_COMPAT_NON_WIN_WINNT_H_
#include <stdint.h>
//! \file
//! \anchor VER_SUITE_x
//! \name VER_SUITE_*
//!
//! \brief Installable product values for MINIDUMP_SYSTEM_INFO::SuiteMask.
//! \{
#define VER_SUITE_SMALLBUSINESS 0x0001
#define VER_SUITE_ENTERPRISE 0x0002
#define VER_SUITE_BACKOFFICE 0x0004
#define VER_SUITE_COMMUNICATIONS 0x0008
#define VER_SUITE_TERMINAL 0x0010
#define VER_SUITE_SMALLBUSINESS_RESTRICTED 0x0020
#define VER_SUITE_EMBEDDEDNT 0x0040
#define VER_SUITE_DATACENTER 0x0080
#define VER_SUITE_SINGLEUSERTS 0x0100
#define VER_SUITE_PERSONAL 0x0200
#define VER_SUITE_BLADE 0x0400
#define VER_SUITE_EMBEDDED_RESTRICTED 0x0800
#define VER_SUITE_SECURITY_APPLIANCE 0x1000
#define VER_SUITE_STORAGE_SERVER 0x2000
#define VER_SUITE_COMPUTE_SERVER 0x4000
#define VER_SUITE_WH_SERVER 0x8000
//! \}
//! \brief The maximum number of exception parameters present in the
//! MINIDUMP_EXCEPTION::ExceptionInformation array.
#define EXCEPTION_MAXIMUM_PARAMETERS 15
//! \anchor PROCESSOR_ARCHITECTURE_x
//! \name PROCESSOR_ARCHITECTURE_*
//!
//! \brief CPU type values for MINIDUMP_SYSTEM_INFO::ProcessorArchitecture.
//!
//! \sa crashpad::MinidumpCPUArchitecture
//! \{
#define PROCESSOR_ARCHITECTURE_INTEL 0
#define PROCESSOR_ARCHITECTURE_MIPS 1
#define PROCESSOR_ARCHITECTURE_ALPHA 2
#define PROCESSOR_ARCHITECTURE_PPC 3
#define PROCESSOR_ARCHITECTURE_SHX 4
#define PROCESSOR_ARCHITECTURE_ARM 5
#define PROCESSOR_ARCHITECTURE_IA64 6
#define PROCESSOR_ARCHITECTURE_ALPHA64 7
#define PROCESSOR_ARCHITECTURE_MSIL 8
#define PROCESSOR_ARCHITECTURE_AMD64 9
#define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10
#define PROCESSOR_ARCHITECTURE_NEUTRAL 11
#define PROCESSOR_ARCHITECTURE_ARM64 12
#define PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64 13
#define PROCESSOR_ARCHITECTURE_UNKNOWN 0xffff
//! \}
//! \anchor PF_x
//! \name PF_*
//!
//! \brief CPU feature values for \ref CPU_INFORMATION::ProcessorFeatures
//! "CPU_INFORMATION::OtherCpuInfo::ProcessorFeatures".
//!
//! \{
#define PF_FLOATING_POINT_PRECISION_ERRATA 0
#define PF_FLOATING_POINT_EMULATED 1
#define PF_COMPARE_EXCHANGE_DOUBLE 2
#define PF_MMX_INSTRUCTIONS_AVAILABLE 3
#define PF_PPC_MOVEMEM_64BIT_OK 4
#define PF_ALPHA_BYTE_INSTRUCTIONS 5
#define PF_XMMI_INSTRUCTIONS_AVAILABLE 6
#define PF_3DNOW_INSTRUCTIONS_AVAILABLE 7
#define PF_RDTSC_INSTRUCTION_AVAILABLE 8
#define PF_PAE_ENABLED 9
#define PF_XMMI64_INSTRUCTIONS_AVAILABLE 10
#define PF_SSE_DAZ_MODE_AVAILABLE 11
#define PF_NX_ENABLED 12
#define PF_SSE3_INSTRUCTIONS_AVAILABLE 13
#define PF_COMPARE_EXCHANGE128 14
#define PF_COMPARE64_EXCHANGE128 15
#define PF_CHANNELS_ENABLED 16
#define PF_XSAVE_ENABLED 17
#define PF_ARM_VFP_32_REGISTERS_AVAILABLE 18
#define PF_ARM_NEON_INSTRUCTIONS_AVAILABLE 19
#define PF_SECOND_LEVEL_ADDRESS_TRANSLATION 20
#define PF_VIRT_FIRMWARE_ENABLED 21
#define PF_RDWRFSGSBASE_AVAILABLE 22
#define PF_FASTFAIL_AVAILABLE 23
#define PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE 24
#define PF_ARM_64BIT_LOADSTORE_ATOMIC 25
#define PF_ARM_EXTERNAL_CACHE_AVAILABLE 26
#define PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE 27
#define PF_RDRAND_INSTRUCTION_AVAILABLE 28
#define PF_ARM_V8_INSTRUCTIONS_AVAILABLE 29
#define PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE 30
#define PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE 31
#define PF_RDTSCP_INSTRUCTION_AVAILABLE 32
//! \}
//! \anchor PAGE_x
//! \name PAGE_*
//!
//! \brief Memory protection constants for MINIDUMP_MEMORY_INFO::Protect and
//! MINIDUMP_MEMORY_INFO::AllocationProtect.
//! \{
#define PAGE_NOACCESS 0x1
#define PAGE_READONLY 0x2
#define PAGE_READWRITE 0x4
#define PAGE_WRITECOPY 0x8
#define PAGE_EXECUTE 0x10
#define PAGE_EXECUTE_READ 0x20
#define PAGE_EXECUTE_READWRITE 0x40
#define PAGE_EXECUTE_WRITECOPY 0x80
#define PAGE_GUARD 0x100
#define PAGE_NOCACHE 0x200
#define PAGE_WRITECOMBINE 0x400
//! \}
//! \anchor MEM_x
//! \name MEM_*
//!
//! \brief Memory state and type constants for MINIDUMP_MEMORY_INFO::State and
//! MINIDUMP_MEMORY_INFO::Type.
//! \{
#define MEM_COMMIT 0x1000
#define MEM_RESERVE 0x2000
#define MEM_DECOMMIT 0x4000
#define MEM_RELEASE 0x8000
#define MEM_FREE 0x10000
#define MEM_PRIVATE 0x20000
#define MEM_MAPPED 0x40000
#define MEM_RESET 0x80000
//! \}
//! \brief The maximum number of distinct identifiable features that could
//! possibly be carried in an XSAVE area.
//!
//! This corresponds to the number of bits in the XSAVE state-component bitmap,
//! XSAVE_BV. See Intel Software Developers Manual, Volume 1: Basic
//! Architecture (253665-060), 13.4.2 “XSAVE Header”.
#define MAXIMUM_XSTATE_FEATURES (64)
//! \brief The location of a single state component within an XSAVE area.
struct XSTATE_FEATURE {
//! \brief The location of a state component within a CPU-specific context
//! structure.
//!
//! This is equivalent to the difference (`ptrdiff_t`) between the return
//! value of `LocateXStateFeature()` and its \a Context argument.
uint32_t Offset;
//! \brief The size of a state component with a CPU-specific context
//! structure.
//!
//! This is equivalent to the size returned by `LocateXStateFeature()` in \a
//! Length.
uint32_t Size;
};
//! \anchor IMAGE_DEBUG_MISC_x
//! \name IMAGE_DEBUG_MISC_*
//!
//! Data type values for IMAGE_DEBUG_MISC::DataType.
//! \{
//! \brief A pointer to a `.dbg` file.
//!
//! IMAGE_DEBUG_MISC::Data will contain the path or file name of the `.dbg` file
//! associated with the module.
#define IMAGE_DEBUG_MISC_EXENAME 1
//! \}
//! \brief Miscellaneous debugging record.
//!
//! This structure is referenced by MINIDUMP_MODULE::MiscRecord. It is obsolete,
//! superseded by the CodeView record.
struct IMAGE_DEBUG_MISC {
//! \brief The type of data carried in the #Data field.
//!
//! This is a value of \ref IMAGE_DEBUG_MISC_x "IMAGE_DEBUG_MISC_*".
uint32_t DataType;
//! \brief The length of this structure in bytes, including the entire #Data
//! field and its `NUL` terminator.
//!
//! \note The Windows documentation states that this field is rounded up to
//! nearest nearest 4-byte multiple.
uint32_t Length;
//! \brief The encoding of the #Data field.
//!
//! If this field is `0`, #Data contains narrow or multibyte character data.
//! If this field is `1`, #Data is UTF-16-encoded.
//!
//! On Windows, with this field set to `0`, #Data will be encoded in the code
//! page of the system that linked the module. On other operating systems,
//! UTF-8 may be used.
uint8_t Unicode;
uint8_t Reserved[3];
//! \brief The data carried within this structure.
//!
//! For string data, this field will be `NUL`-terminated. If #Unicode is `1`,
//! this field is UTF-16-encoded, and will be terminated by a UTF-16 `NUL`
//! code unit (two `NUL` bytes).
uint8_t Data[1];
};
//! \anchor VER_NT_x
//! \name VER_NT_*
//!
//! \brief Operating system type values for MINIDUMP_SYSTEM_INFO::ProductType.
//!
//! \sa crashpad::MinidumpOSType
//! \{
#define VER_NT_WORKSTATION 1
#define VER_NT_DOMAIN_CONTROLLER 2
#define VER_NT_SERVER 3
//! \}
//! \anchor VER_PLATFORM_x
//! \name VER_PLATFORM_*
//!
//! \brief Operating system family values for MINIDUMP_SYSTEM_INFO::PlatformId.
//!
//! \sa crashpad::MinidumpOS
//! \{
#define VER_PLATFORM_WIN32s 0
#define VER_PLATFORM_WIN32_WINDOWS 1
#define VER_PLATFORM_WIN32_NT 2
//! \}
#endif // CRASHPAD_COMPAT_NON_WIN_WINNT_H_
@@ -0,0 +1,20 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_WIN_GETOPT_H_
#define CRASHPAD_COMPAT_WIN_GETOPT_H_
#include "third_party/getopt/getopt.h"
#endif // CRASHPAD_COMPAT_WIN_GETOPT_H_
@@ -0,0 +1,28 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_WIN_STRINGS_H_
#define CRASHPAD_COMPAT_WIN_STRINGS_H_
#ifdef __cplusplus
extern "C" {
#endif
int strcasecmp(const char* s1, const char* s2);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // CRASHPAD_COMPAT_WIN_STRINGS_H_
@@ -0,0 +1,20 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_WIN_SYS_TIME_H_
#define CRASHPAD_COMPAT_WIN_SYS_TIME_H_
#include <winsock2.h>
#endif // CRASHPAD_COMPAT_WIN_SYS_TIME_H_
@@ -0,0 +1,23 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_WIN_SYS_TYPES_H_
#define CRASHPAD_COMPAT_WIN_SYS_TYPES_H_
// This is intended to be roughly equivalent to #include_next.
#include <../ucrt/sys/types.h>
#include <stdint.h>
#endif // CRASHPAD_COMPAT_WIN_SYS_TYPES_H_
+37
View File
@@ -0,0 +1,37 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_WIN_TIME_H_
#define CRASHPAD_COMPAT_WIN_TIME_H_
// This is intended to be roughly equivalent to #include_next.
#include <../ucrt/time.h>
#ifdef __cplusplus
extern "C" {
#endif
struct tm* gmtime_r(const time_t* timep, struct tm* result);
struct tm* localtime_r(const time_t* timep, struct tm* result);
const char* strptime(const char* buf, const char* format, struct tm* tm);
time_t timegm(struct tm* tm);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // CRASHPAD_COMPAT_WIN_TIME_H_
@@ -0,0 +1,27 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_WIN_WINBASE_H_
#define CRASHPAD_COMPAT_WIN_WINBASE_H_
// include_next <winbase.h>
#include <../um/winbase.h>
// 10.0.15063.0 SDK
#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
#define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x2)
#endif
#endif // CRASHPAD_COMPAT_WIN_WINBASE_H_
+60
View File
@@ -0,0 +1,60 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_WIN_WINNT_H_
#define CRASHPAD_COMPAT_WIN_WINNT_H_
// include_next <winnt.h>
#include <../um/winnt.h>
// https://msdn.microsoft.com/library/aa373184.aspx: "Note that this structure
// definition was accidentally omitted from WinNT.h."
struct PROCESSOR_POWER_INFORMATION {
ULONG Number;
ULONG MaxMhz;
ULONG CurrentMhz;
ULONG MhzLimit;
ULONG MaxIdleState;
ULONG CurrentIdleState;
};
// 10.0.10240.0 SDK
#ifndef PROCESSOR_ARCHITECTURE_ARM64
#define PROCESSOR_ARCHITECTURE_ARM64 12
#endif
#ifndef PF_ARM_V8_INSTRUCTIONS_AVAILABLE
#define PF_ARM_V8_INSTRUCTIONS_AVAILABLE 29
#endif
#ifndef PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE
#define PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE 30
#endif
#ifndef PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE
#define PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE 31
#endif
#ifndef PF_RDTSCP_INSTRUCTION_AVAILABLE
#define PF_RDTSCP_INSTRUCTION_AVAILABLE 32
#endif
// 10.0.14393.0 SDK
#ifndef PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64
#define PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64 13
#endif
#endif // CRASHPAD_COMPAT_WIN_WINNT_H_
@@ -0,0 +1,25 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_COMPAT_WIN_WINTERNL_H_
#define CRASHPAD_COMPAT_WIN_WINTERNL_H_
// include_next <winternl.h>
#include <../um/winternl.h>
// 10.0.16299.0 SDK
typedef struct _CLIENT_ID CLIENT_ID;
#endif // CRASHPAD_COMPAT_WIN_WINTERNL_H_
@@ -0,0 +1,177 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_HANDLER_CRASH_REPORT_UPLOAD_THREAD_H_
#define CRASHPAD_HANDLER_CRASH_REPORT_UPLOAD_THREAD_H_
#include <memory>
#include <string>
#include "base/macros.h"
#include "client/crash_report_database.h"
#include "util/misc/uuid.h"
#include "util/stdlib/thread_safe_vector.h"
#include "util/thread/worker_thread.h"
namespace crashpad {
//! \brief A thread that processes pending crash reports in a
//! CrashReportDatabase by uploading them or marking them as completed
//! without upload, as desired.
//!
//! A producer of crash reports should notify an object of this class that a new
//! report has been added to the database by calling ReportPending().
//!
//! Independently of being triggered by ReportPending(), objects of this class
//! can periodically examine the database for pending reports. This allows
//! failed upload attempts for reports left in the pending state to be retried.
//! It also catches reports that are added without a ReportPending() signal
//! being caught. This may happen if crash reports are added to the database by
//! other processes.
class CrashReportUploadThread : public WorkerThread::Delegate {
public:
//! \brief Options to be passed to the CrashReportUploadThread constructor.
struct Options {
//! Whether client identifying parameters like product name or version
//! should be added to the URL.
bool identify_client_via_url;
//! Whether uploads should be throttled to a (currently hardcoded) rate.
bool rate_limit;
//! Whether uploads should use `gzip` compression.
bool upload_gzip;
//! Whether to periodically check for new pending reports not already known
//! to exist. When `false`, only an initial upload attempt will be made for
//! reports known to exist by having been added by the ReportPending()
//! method. No scans for new pending reports will be conducted.
bool watch_pending_reports;
};
//! \brief Constructs a new object.
//!
//! \param[in] database The database to upload crash reports from.
//! \param[in] url The URL of the server to upload crash reports to.
//! \param[in] options Options for the report uploads.
CrashReportUploadThread(CrashReportDatabase* database,
const std::string& url,
const Options& options);
~CrashReportUploadThread();
//! \brief Starts a dedicated upload thread, which executes ThreadMain().
//!
//! This method may only be be called on a newly-constructed object or after
//! a call to Stop().
void Start();
//! \brief Stops the upload thread.
//!
//! The upload thread will terminate after completing whatever task it is
//! performing. If it is not performing any task, it will terminate
//! immediately. This method blocks while waiting for the upload thread to
//! terminate.
//!
//! This method must only be called after Start(). If Start() has been called,
//! this method must be called before destroying an object of this class.
//!
//! This method may be called from any thread other than the upload thread.
//! It is expected to only be called from the same thread that called Start().
void Stop();
//! \brief Informs the upload thread that a new pending report has been added
//! to the database.
//!
//! \param[in] report_uuid The unique identifier of the newly added pending
//! report.
//!
//! This method may be called from any thread.
void ReportPending(const UUID& report_uuid);
private:
//! \brief The result code from UploadReport().
enum class UploadResult {
//! \brief The crash report was uploaded successfully.
kSuccess,
//! \brief The crash report upload failed in such a way that recovery is
//! impossible.
//!
//! No further upload attempts should be made for the report.
kPermanentFailure,
//! \brief The crash report upload failed, but it might succeed again if
//! retried in the future.
//!
//! If the report has not already been retried too many times, the caller
//! may arrange to call UploadReport() for the report again in the future,
//! after a suitable delay.
kRetry,
};
//! \brief Calls ProcessPendingReport() on pending reports.
//!
//! Assuming Stop() has not been called, this will process reports that the
//! object has been made aware of in ReportPending(). Additionally, if the
//! object was constructed with \a watch_pending_reports, it will also scan
//! the crash report database for other pending reports, and process those as
//! well.
void ProcessPendingReports();
//! \brief Processes a single pending report from the database.
//!
//! \param[in] report The crash report to process.
//!
//! If report upload is enabled, this method attempts to upload \a report by
//! calling UplaodReport(). If the upload is successful, the report will be
//! marked as “completed” in the database. If the upload fails and more
//! retries are desired, the reports upload-attempt count and
//! last-upload-attempt time will be updated in the database and it will
//! remain in the “pending” state. If the upload fails and no more retries are
//! desired, or report upload is disabled, it will be marked as “completed” in
//! the database without ever having been uploaded.
void ProcessPendingReport(const CrashReportDatabase::Report& report);
//! \brief Attempts to upload a crash report.
//!
//! \param[in] report The report to upload. The caller is responsible for
//! calling CrashReportDatabase::GetReportForUploading() before calling
//! this method, and for calling
//! CrashReportDatabase::RecordUploadAttempt() after calling this method.
//! \param[out] response_body If the upload attempt is successful, this will
//! be set to the response body sent by the server. Breakpad-type servers
//! provide the crash ID assigned by the server in the response body.
//!
//! \return A member of UploadResult indicating the result of the upload
//! attempt.
UploadResult UploadReport(const CrashReportDatabase::Report* report,
std::string* response_body);
// WorkerThread::Delegate:
//! \brief Calls ProcessPendingReports() in response to ReportPending() having
//! been called on any thread, as well as periodically on a timer.
void DoWork(const WorkerThread* thread) override;
const Options options_;
const std::string url_;
WorkerThread thread_;
ThreadSafeVector<UUID> known_pending_report_uuids_;
CrashReportDatabase* database_; // weak
DISALLOW_COPY_AND_ASSIGN(CrashReportUploadThread);
};
} // namespace crashpad
#endif // CRASHPAD_HANDLER_CRASH_REPORT_UPLOAD_THREAD_H_
@@ -0,0 +1,65 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_HANDLER_FUCHSIA_CRASH_REPORT_EXCEPTION_HANDLER_H_
#define CRASHPAD_HANDLER_FUCHSIA_CRASH_REPORT_EXCEPTION_HANDLER_H_
#include <map>
#include <string>
#include "base/macros.h"
#include "client/crash_report_database.h"
#include "handler/crash_report_upload_thread.h"
#include "handler/user_stream_data_source.h"
namespace crashpad {
//! \brief An exception handler that writes crash reports for exception messages
//! to a CrashReportDatabase. This class is not yet implemented.
class CrashReportExceptionHandler {
public:
//! \brief Creates a new object that will store crash reports in \a database.
//!
//! \param[in] database The database to store crash reports in. Weak.
//! \param[in] upload_thread The upload thread to notify when a new crash
//! report is written into \a database.
//! \param[in] process_annotations A map of annotations to insert as
//! process-level annotations into each crash report that is written. Do
//! not confuse this with module-level annotations, which are under the
//! control of the crashing process, and are used to implement Chrome's
//! "crash keys." Process-level annotations are those that are beyond the
//! control of the crashing process, which must reliably be set even if
//! the process crashes before its able to establish its own annotations.
//! To interoperate with Breakpad servers, the recommended practice is to
//! specify values for the `"prod"` and `"ver"` keys as process
//! annotations.
//! \param[in] user_stream_data_sources Data sources to be used to extend
//! crash reports. For each crash report that is written, the data sources
//! are called in turn. These data sources may contribute additional
//! minidump streams. `nullptr` if not required.
CrashReportExceptionHandler(
CrashReportDatabase* database,
CrashReportUploadThread* upload_thread,
const std::map<std::string, std::string>* process_annotations,
const UserStreamDataSources* user_stream_data_sources);
~CrashReportExceptionHandler();
private:
DISALLOW_COPY_AND_ASSIGN(CrashReportExceptionHandler);
};
} // namespace crashpad
#endif // CRASHPAD_HANDLER_FUCHSIA_CRASH_REPORT_EXCEPTION_HANDLER_H_
@@ -0,0 +1,44 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_HANDLER_FUCHSIA_EXCEPTION_HANDLER_SERVER_H_
#define CRASHPAD_HANDLER_FUCHSIA_EXCEPTION_HANDLER_SERVER_H_
#include "base/macros.h"
namespace crashpad {
class CrashReportExceptionHandler;
//! \brief Runs the main exception-handling server in Crashpad's handler
//! process. This class is not yet implemented.
class ExceptionHandlerServer {
public:
//! \brief Constructs an ExceptionHandlerServer object.
ExceptionHandlerServer();
~ExceptionHandlerServer();
//! \brief Runs the exception-handling server.
//!
//! \param[in] handler The handler to which the exceptions are delegated when
//! they are caught in Run(). Ownership is not transferred.
void Run(CrashReportExceptionHandler* handler);
private:
DISALLOW_COPY_AND_ASSIGN(ExceptionHandlerServer);
};
} // namespace crashpad
#endif // CRASHPAD_HANDLER_FUCHSIA_EXCEPTION_HANDLER_SERVER_H_
@@ -0,0 +1,39 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_HANDLER_HANDLER_MAIN_H_
#define CRASHPAD_HANDLER_HANDLER_MAIN_H_
#include "handler/user_stream_data_source.h"
namespace crashpad {
//! \brief The `main()` of the `crashpad_handler` binary.
//!
//! This is exposed so that `crashpad_handler` can be embedded into another
//! binary, but called and used as if it were a standalone executable.
//!
//! \param[in] argc \a argc as passed to `main()`.
//! \param[in] argv \a argv as passed to `main()`.
//! \param[in] user_stream_sources An optional vector containing the
//! extensibility data sources to call on crash. Each time a minidump is
//! created, the sources are called in turn. Any streams returned are added
//! to the minidump.
int HandlerMain(int argc,
char* argv[],
const UserStreamDataSources* user_stream_sources);
} // namespace crashpad
#endif // CRASHPAD_HANDLER_HANDLER_MAIN_H_
@@ -0,0 +1,155 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_HANDLER_LINUX_EXCEPTION_HANDLER_SERVER_H_
#define CRASHPAD_HANDLER_LINUX_EXCEPTION_HANDLER_SERVER_H_
#include <stdint.h>
#include <sys/socket.h>
#include <memory>
#include <unordered_map>
#include "base/macros.h"
#include "util/file/file_io.h"
#include "util/linux/exception_handler_protocol.h"
#include "util/misc/address_types.h"
#include "util/misc/initialization_state_dcheck.h"
namespace crashpad {
//! \brief Abstract base class for deciding how the handler should `ptrace` a
//! client.
class PtraceStrategyDecider {
public:
virtual ~PtraceStrategyDecider() = default;
//! \brief The possible return values for ChooseStrategy().
enum class Strategy {
//! \brief An error occurred, with a message logged.
kError,
//! \brief Ptrace cannot be used.
kNoPtrace,
//! \brief The handler should `ptrace`-attach the client directly.
kDirectPtrace,
//! \brief The client should `fork` a PtraceBroker for the handler.
kForkBroker,
};
//! \brief Chooses an appropriate `ptrace` strategy.
//!
//! \param[in] sock A socket conncted to a ExceptionHandlerClient.
//! \param[in] client_credentials The credentials for the connected client.
//! \return the chosen #Strategy.
virtual Strategy ChooseStrategy(int sock,
const ucred& client_credentials) = 0;
protected:
PtraceStrategyDecider() = default;
};
//! \brief Runs the main exception-handling server in Crashpads handler
//! process.
class ExceptionHandlerServer {
public:
class Delegate {
public:
//! \brief Called on receipt of a crash dump request from a client.
//!
//! \param[in] client_process_id The process ID of the crashing client.
//! \param[in] exception_information_address The address in the client's
//! address space of an ExceptionInformation struct.
//! \return `true` on success. `false` on failure with a message logged.
virtual bool HandleException(pid_t client_process_id,
VMAddress exception_information_address) = 0;
//! \brief Called on the receipt of a crash dump request from a client for a
//! crash that should be mediated by a PtraceBroker.
//!
//! \param[in] client_process_id The process ID of the crashing client.
//! \param[in] exception_information_address The address in the client's
//! address space of an ExceptionInformation struct.
//! \param[in] broker_sock A socket connected to the PtraceBroker.
//! \return `true` on success. `false` on failure with a message logged.
virtual bool HandleExceptionWithBroker(
pid_t client_process_id,
VMAddress exception_information_address,
int broker_sock) = 0;
protected:
~Delegate() {}
};
ExceptionHandlerServer();
~ExceptionHandlerServer();
//! \brief Sets the handler's PtraceStrategyDecider.
//!
//! If this method is not called, a default PtraceStrategyDecider will be
//! used.
void SetPtraceStrategyDecider(std::unique_ptr<PtraceStrategyDecider> decider);
//! \brief Initializes this object.
//!
//! This method must be successfully called before Run().
//!
//! \param[in] sock A socket on which to receive client requests.
//! \return `true` on success. `false` on failure with a message logged.
bool InitializeWithClient(ScopedFileHandle sock);
//! \brief Runs the exception-handling server.
//!
//! This method must only be called once on an ExceptionHandlerServer object.
//! This method returns when there are no more client connections or Stop()
//! has been called.
//!
//! \param[in] delegate An object to send exceptions to.
void Run(Delegate* delegate);
//! \brief Stops a running exception-handling server.
//!
//! Stop() may be called at any time, and may be called from a signal handler.
//! If Stop() is called before Run() it will cause Run() to return as soon as
//! it is called. It is harmless to call Stop() after Run() has already
//! returned, or to call Stop() after it has already been called.
void Stop();
private:
struct Event;
void HandleEvent(Event* event, uint32_t event_type);
bool InstallClientSocket(ScopedFileHandle socket);
bool UninstallClientSocket(Event* event);
bool ReceiveClientMessage(Event* event);
bool HandleCrashDumpRequest(const msghdr& msg,
const ClientInformation& client_info,
int client_sock);
std::unordered_map<int, std::unique_ptr<Event>> clients_;
std::unique_ptr<Event> shutdown_event_;
std::unique_ptr<PtraceStrategyDecider> strategy_decider_;
Delegate* delegate_;
ScopedFileHandle pollfd_;
bool keep_running_;
InitializationStateDcheck initialized_;
DISALLOW_COPY_AND_ASSIGN(ExceptionHandlerServer);
};
} // namespace crashpad
#endif // CRASHPAD_HANDLER_LINUX_EXCEPTION_HANDLER_SERVER_H_
@@ -0,0 +1,93 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_HANDLER_MAC_CRASH_REPORT_EXCEPTION_HANDLER_H_
#define CRASHPAD_HANDLER_MAC_CRASH_REPORT_EXCEPTION_HANDLER_H_
#include <mach/mach.h>
#include <map>
#include <string>
#include "base/macros.h"
#include "client/crash_report_database.h"
#include "handler/crash_report_upload_thread.h"
#include "handler/user_stream_data_source.h"
#include "util/mach/exc_server_variants.h"
namespace crashpad {
//! \brief An exception handler that writes crash reports for exception messages
//! to a CrashReportDatabase.
class CrashReportExceptionHandler : public UniversalMachExcServer::Interface {
public:
//! \brief Creates a new object that will store crash reports in \a database.
//!
//! \param[in] database The database to store crash reports in. Weak.
//! \param[in] upload_thread The upload thread to notify when a new crash
//! report is written into \a database.
//! \param[in] process_annotations A map of annotations to insert as
//! process-level annotations into each crash report that is written. Do
//! not confuse this with module-level annotations, which are under the
//! control of the crashing process, and are used to implement Chromes
//! “crash keys.” Process-level annotations are those that are beyond the
//! control of the crashing process, which must reliably be set even if
//! the process crashes before its able to establish its own annotations.
//! To interoperate with Breakpad servers, the recommended practice is to
//! specify values for the `"prod"` and `"ver"` keys as process
//! annotations.
//! \param[in] user_stream_data_sources Data sources to be used to extend
//! crash reports. For each crash report that is written, the data sources
//! are called in turn. These data sources may contribute additional
//! minidump streams. `nullptr` if not required.
CrashReportExceptionHandler(
CrashReportDatabase* database,
CrashReportUploadThread* upload_thread,
const std::map<std::string, std::string>* process_annotations,
const UserStreamDataSources* user_stream_data_sources);
~CrashReportExceptionHandler();
// UniversalMachExcServer::Interface:
//! \brief Processes an exception message by writing a crash report to this
//! objects CrashReportDatabase.
kern_return_t CatchMachException(
exception_behavior_t behavior,
exception_handler_t exception_port,
thread_t thread,
task_t task,
exception_type_t exception,
const mach_exception_data_type_t* code,
mach_msg_type_number_t code_count,
thread_state_flavor_t* flavor,
ConstThreadState old_state,
mach_msg_type_number_t old_state_count,
thread_state_t new_state,
mach_msg_type_number_t* new_state_count,
const mach_msg_trailer_t* trailer,
bool* destroy_complex_request) override;
private:
CrashReportDatabase* database_; // weak
CrashReportUploadThread* upload_thread_; // weak
const std::map<std::string, std::string>* process_annotations_; // weak
const UserStreamDataSources* user_stream_data_sources_; // weak
DISALLOW_COPY_AND_ASSIGN(CrashReportExceptionHandler);
};
} // namespace crashpad
#endif // CRASHPAD_HANDLER_MAC_CRASH_REPORT_EXCEPTION_HANDLER_H_
@@ -0,0 +1,82 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_HANDLER_MAC_EXCEPTION_HANDLER_SERVER_H_
#define CRASHPAD_HANDLER_MAC_EXCEPTION_HANDLER_SERVER_H_
#include <mach/mach.h>
#include "base/mac/scoped_mach_port.h"
#include "base/macros.h"
#include "util/mach/exc_server_variants.h"
namespace crashpad {
//! \brief Runs the main exception-handling server in Crashpads handler
//! process.
class ExceptionHandlerServer {
public:
//! \brief Constructs an ExceptionHandlerServer object.
//!
//! \param[in] receive_port The port that exception messages and no-senders
//! notifications will be received on.
//! \param[in] launchd If `true`, the exception handler is being run from
//! launchd. \a receive_port is not monitored for no-senders
//! notifications, and instead, Stop() must be called to provide a “quit”
//! signal.
ExceptionHandlerServer(base::mac::ScopedMachReceiveRight receive_port,
bool launchd);
~ExceptionHandlerServer();
//! \brief Runs the exception-handling server.
//!
//! \param[in] exception_interface An object to send exception messages to.
//!
//! This method monitors the receive port for exception messages and, if
//! not being run by launchd, no-senders notifications. It continues running
//! until it has no more clients, indicated by the receipt of a no-senders
//! notification, or until Stop() is called. When not being run by launchd, it
//! is important to assure that a send right exists in a client (or has been
//! queued by `mach_msg()` to be sent to a client) prior to calling this
//! method, or it will detect that it is sender-less and return immediately.
//!
//! All exception messages will be passed to \a exception_interface.
//!
//! This method must only be called once on an ExceptionHandlerServer object.
//!
//! If an unexpected condition that prevents this method from functioning is
//! encountered, it will log a message and terminate execution. Receipt of an
//! invalid message on the receive port will cause a message to be logged, but
//! this method will continue running normally.
void Run(UniversalMachExcServer::Interface* exception_interface);
//! \brief Stops a running exception-handling server.
//!
//! Stop() may be called at any time, and may be called from a signal handler.
//! If Stop() is called before Run() it will cause Run() to return as soon as
//! it is called. It is harmless to call Stop() after Run() has already
//! returned, or to call Stop() after it has already been called.
void Stop();
private:
base::mac::ScopedMachReceiveRight receive_port_;
base::mac::ScopedMachReceiveRight notify_port_;
bool launchd_;
DISALLOW_COPY_AND_ASSIGN(ExceptionHandlerServer);
};
} // namespace crashpad
#endif // CRASHPAD_HANDLER_MAC_EXCEPTION_HANDLER_SERVER_H_
@@ -0,0 +1,38 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_HANDLER_MAC_FILE_LIMIT_ANNOTATION_H_
#define CRASHPAD_HANDLER_MAC_FILE_LIMIT_ANNOTATION_H_
namespace crashpad {
//! \brief Records a `"file-limits"` simple annotation for the process.
//!
//! This annotation will be used to confirm the theory that certain crashes are
//! caused by systems at or near their file descriptor table size limits.
//!
//! The format of the annotation is four comma-separated values: the system-wide
//! `kern.num_files` and `kern.maxfiles` values from `sysctl()`, and the
//! process-specific current and maximum file descriptor limits from
//! `getrlimit(RLIMIT_NOFILE, …)`.
//!
//! See https://crashpad.chromium.org/bug/180.
//!
//! TODO(mark): Remove this annotation after sufficient data has been collected
//! for analysis.
void RecordFileLimitAnnotation();
} // namespace crashpad
#endif // CRASHPAD_HANDLER_MAC_FILE_LIMIT_ANNOTATION_H_
@@ -0,0 +1,61 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef HANDLER_MINIDUMP_TO_UPLOAD_PARAMETERS_H_
#define HANDLER_MINIDUMP_TO_UPLOAD_PARAMETERS_H_
#include <map>
#include <string>
#include "snapshot/process_snapshot.h"
namespace crashpad {
//! \brief Given a ProcessSnapshot, returns a map of key-value pairs to use as
//! HTTP form parameters for upload to a Breakpad crash report colleciton
//! server.
//!
//! The map is built by combining the process simple annotations map with
//! each modules simple annotations map and annotation objects.
//!
//! In the case of duplicate simple map keys or annotation names, the map will
//! retain the first value found for any key, and will log a warning about
//! discarded values. The precedence rules for annotation names are: the two
//! reserved keys discussed below, process simple annotations, module simple
//! annotations, and module annotation objects.
//!
//! For annotation objects, only ones of that are Annotation::Type::kString are
//! included.
//!
//! Each modules annotations vector is also examined and built into a single
//! string value, with distinct elements separated by newlines, and stored at
//! the key named “list_annotations”, which supersedes any other key found by
//! that name.
//!
//! The client ID stored in the minidump is converted to a string and stored at
//! the key named “guid”, which supersedes any other key found by that name.
//!
//! In the event of an error reading the minidump file, a message will be
//! logged.
//!
//! \param[in] process_snapshot The process snapshot from which annotations
//! will be extracted.
//!
//! \returns A string map of the annotations.
std::map<std::string, std::string> BreakpadHTTPFormParametersFromMinidump(
const ProcessSnapshot* process_snapshot);
} // namespace crashpad
#endif // HANDLER_MINIDUMP_TO_UPLOAD_PARAMETERS_H_
@@ -0,0 +1,76 @@
// Copyright 2016 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_HANDLER_PRUNE_CRASH_REPORTS_THREAD_H_
#define CRASHPAD_HANDLER_PRUNE_CRASH_REPORTS_THREAD_H_
#include <memory>
#include "base/macros.h"
#include "util/thread/worker_thread.h"
namespace crashpad {
class CrashReportDatabase;
class PruneCondition;
//! \brief A thread that periodically prunes crash reports from the database
//! using the specified condition.
//!
//! After the thread is started, the database is pruned using the condition
//! every 24 hours. Upon calling Start(), the thread waits 10 minutes before
//! performing the initial prune operation.
class PruneCrashReportThread : public WorkerThread::Delegate {
public:
//! \brief Constructs a new object.
//!
//! \param[in] database The database to prune crash reports from.
//! \param[in] condition The condition used to evaluate crash reports for
//! pruning.
PruneCrashReportThread(CrashReportDatabase* database,
std::unique_ptr<PruneCondition> condition);
~PruneCrashReportThread();
//! \brief Starts a dedicated pruning thread.
//!
//! The thread waits before running the initial prune, so as to not interfere
//! with any startup-related IO performed by the client.
//!
//! This method may only be be called on a newly-constructed object or after
//! a call to Stop().
void Start();
//! \brief Stops the pruning thread.
//!
//! This method must only be called after Start(). If Start() has been called,
//! this method must be called before destroying an object of this class.
//!
//! This method may be called from any thread other than the pruning thread.
//! It is expected to only be called from the same thread that called Start().
void Stop();
private:
// WorkerThread::Delegate:
void DoWork(const WorkerThread* thread) override;
WorkerThread thread_;
std::unique_ptr<PruneCondition> condition_;
CrashReportDatabase* database_; // weak
DISALLOW_COPY_AND_ASSIGN(PruneCrashReportThread);
};
} // namespace crashpad
#endif // CRASHPAD_HANDLER_PRUNE_CRASH_REPORTS_THREAD_H_
@@ -0,0 +1,68 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_HANDLER_USER_STREAM_DATA_SOURCE_H_
#define CRASHPAD_HANDLER_USER_STREAM_DATA_SOURCE_H_
#include <memory>
#include <vector>
namespace crashpad {
class MinidumpFileWriter;
class MinidumpUserExtensionStreamDataSource;
class ProcessSnapshot;
//! \brief Extensibility interface for embedders who wish to add custom streams
//! to minidumps.
class UserStreamDataSource {
public:
virtual ~UserStreamDataSource() {}
//! \brief Produce the contents for an extension stream for a crashed program.
//!
//! Called after \a process_snapshot has been initialized for the crashed
//! process to (optionally) produce the contents of a user extension stream
//! that will be attached to the minidump.
//!
//! \param[in] process_snapshot An initialized snapshot for the crashed
//! process.
//!
//! \return A new data source for the stream to add to the minidump or
//! `nullptr` on failure or to opt out of adding a stream.
virtual std::unique_ptr<MinidumpUserExtensionStreamDataSource>
ProduceStreamData(ProcessSnapshot* process_snapshot) = 0;
};
using UserStreamDataSources =
std::vector<std::unique_ptr<UserStreamDataSource>>;
//! \brief Adds user extension streams to a minidump.
//!
//! Dispatches to each source in \a user_stream_data_sources and adds returned
//! extension streams to \a minidump_file_writer.
//!
//! \param[in] user_stream_data_sources A pointer to the data sources, or
//! `nullptr`.
//! \param[in] process_snapshot An initialized snapshot to the crashing process.
//! \param[in] minidump_file_writer Any extension streams will be added to this
//! minidump.
void AddUserExtensionStreams(
const UserStreamDataSources* user_stream_data_sources,
ProcessSnapshot* process_snapshot,
MinidumpFileWriter* minidump_file_writer);
} // namespace crashpad
#endif // CRASHPAD_HANDLER_USER_STREAM_DATA_SOURCE_H_
@@ -0,0 +1,84 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_HANDLER_WIN_CRASH_REPORT_EXCEPTION_HANDLER_H_
#define CRASHPAD_HANDLER_WIN_CRASH_REPORT_EXCEPTION_HANDLER_H_
#include <windows.h>
#include <map>
#include <string>
#include "base/macros.h"
#include "handler/user_stream_data_source.h"
#include "util/win/exception_handler_server.h"
namespace crashpad {
class CrashReportDatabase;
class CrashReportUploadThread;
//! \brief An exception handler that writes crash reports for exception messages
//! to a CrashReportDatabase.
class CrashReportExceptionHandler : public ExceptionHandlerServer::Delegate {
public:
//! \brief Creates a new object that will store crash reports in \a database.
//!
//! \param[in] database The database to store crash reports in. Weak.
//! \param[in] upload_thread The upload thread to notify when a new crash
//! report is written into \a database.
//! \param[in] process_annotations A map of annotations to insert as
//! process-level annotations into each crash report that is written. Do
//! not confuse this with module-level annotations, which are under the
//! control of the crashing process, and are used to implement Chrome's
//! "crash keys." Process-level annotations are those that are beyond the
//! control of the crashing process, which must reliably be set even if
//! the process crashes before it's able to establish its own annotations.
//! To interoperate with Breakpad servers, the recommended practice is to
//! specify values for the `"prod"` and `"ver"` keys as process
//! annotations.
//! \param[in] user_stream_data_sources Data sources to be used to extend
//! crash reports. For each crash report that is written, the data sources
//! are called in turn. These data sources may contribute additional
//! minidump streams. `nullptr` if not required.
CrashReportExceptionHandler(
CrashReportDatabase* database,
CrashReportUploadThread* upload_thread,
const std::map<std::string, std::string>* process_annotations,
const UserStreamDataSources* user_stream_data_sources);
~CrashReportExceptionHandler();
// ExceptionHandlerServer::Delegate:
//! \brief Processes an exception message by writing a crash report to this
//! object's CrashReportDatabase.
void ExceptionHandlerServerStarted() override;
unsigned int ExceptionHandlerServerException(
HANDLE process,
WinVMAddress exception_information_address,
WinVMAddress debug_critical_section_address) override;
private:
CrashReportDatabase* database_; // weak
CrashReportUploadThread* upload_thread_; // weak
const std::map<std::string, std::string>* process_annotations_; // weak
const UserStreamDataSources* user_stream_data_sources_; // weak
DISALLOW_COPY_AND_ASSIGN(CrashReportExceptionHandler);
};
} // namespace crashpad
#endif // CRASHPAD_HANDLER_WIN_CRASH_REPORT_EXCEPTION_HANDLER_H_
@@ -0,0 +1,109 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_ANNOTATION_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_ANNOTATION_WRITER_H_
#include <memory>
#include <vector>
#include "minidump/minidump_byte_array_writer.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_string_writer.h"
#include "minidump/minidump_writable.h"
#include "snapshot/annotation_snapshot.h"
namespace crashpad {
//! \brief The writer for a MinidumpAnnotation object in a minidump file.
//!
//! Because MinidumpAnnotation objects only appear as elements
//! of MinidumpAnnotationList objects, this class does not write any
//! data on its own. It makes its MinidumpAnnotation data available to its
//! MinidumpAnnotationList parent, which writes it as part of a
//! MinidumpAnnotationList.
class MinidumpAnnotationWriter final : public internal::MinidumpWritable {
public:
MinidumpAnnotationWriter();
~MinidumpAnnotationWriter();
//! \brief Initializes the annotation writer with data from an
//! AnnotationSnapshot.
void InitializeFromSnapshot(const AnnotationSnapshot& snapshot);
//! \brief Initializes the annotation writer with data values.
void InitializeWithData(const std::string& name,
uint16_t type,
const std::vector<uint8_t>& data);
//! \brief Returns the MinidumpAnnotation referencing this objects data.
const MinidumpAnnotation* minidump_annotation() const { return &annotation_; }
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<internal::MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
MinidumpAnnotation annotation_;
internal::MinidumpUTF8StringWriter name_;
MinidumpByteArrayWriter value_;
DISALLOW_COPY_AND_ASSIGN(MinidumpAnnotationWriter);
};
//! \brief The writer for a MinidumpAnnotationList object in a minidump file,
//! containing a list of MinidumpAnnotation objects.
class MinidumpAnnotationListWriter final : public internal::MinidumpWritable {
public:
MinidumpAnnotationListWriter();
~MinidumpAnnotationListWriter();
//! \brief Initializes the annotation list writer with a list of
//! AnnotationSnapshot objects.
void InitializeFromList(const std::vector<AnnotationSnapshot>& list);
//! \brief Adds a single MinidumpAnnotationWriter to the list to be written.
void AddObject(std::unique_ptr<MinidumpAnnotationWriter> annotation_writer);
//! \brief Determines whether the object is useful.
//!
//! A useful object is one that carries data that makes a meaningful
//! contribution to a minidump file. An object carrying entries would be
//! considered useful.
//!
//! \return `true` if the object is useful, `false` otherwise.
bool IsUseful() const;
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<internal::MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
std::unique_ptr<MinidumpAnnotationList> minidump_list_;
std::vector<std::unique_ptr<MinidumpAnnotationWriter>> objects_;
DISALLOW_COPY_AND_ASSIGN(MinidumpAnnotationListWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_ANNOTATION_WRITER_H_
@@ -0,0 +1,65 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_BYTE_ARRAY_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_BYTE_ARRAY_WRITER_H_
#include <memory>
#include <vector>
#include "base/macros.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_writable.h"
namespace crashpad {
//! \brief Writes a variable-length byte array for a minidump into a
//! \sa MinidumpByteArray.
class MinidumpByteArrayWriter final : public internal::MinidumpWritable {
public:
MinidumpByteArrayWriter();
~MinidumpByteArrayWriter() override;
//! \brief Sets the data to be written.
//!
//! \note Valid in #kStateMutable.
void set_data(const std::vector<uint8_t>& data) { data_ = data; }
//! \brief Sets the data to be written.
//!
//! \note Valid in #kStateMutable.
void set_data(const uint8_t* data, size_t size);
//! \brief Gets the data to be written.
//!
//! \note Valid in any state.
const std::vector<uint8_t>& data() const { return data_; }
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
std::unique_ptr<MinidumpByteArray> minidump_array_;
std::vector<uint8_t> data_;
DISALLOW_COPY_AND_ASSIGN(MinidumpByteArrayWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_BYTE_ARRAY_WRITER_H_
@@ -0,0 +1,341 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_H_
#include <stdint.h>
#include "base/compiler_specific.h"
#include "snapshot/cpu_context.h"
#include "util/numeric/int128.h"
namespace crashpad {
//! \brief Architecture-independent flags for `context_flags` fields in Minidump
//! context structures.
//
// https://zachsaw.blogspot.com/2010/11/wow64-bug-getthreadcontext-may-return.html#c5639760895973344002
enum MinidumpContextFlags : uint32_t {
//! \brief The thread was executing a trap handler in kernel mode
//! (`CONTEXT_EXCEPTION_ACTIVE`).
//!
//! If this bit is set, it indicates that the context is from a thread that
//! was executing a trap handler in the kernel. This bit is only valid when
//! ::kMinidumpContextExceptionReporting is also set. This bit is only used on
//! Windows.
kMinidumpContextExceptionActive = 0x08000000,
//! \brief The thread was executing a system call in kernel mode
//! (`CONTEXT_SERVICE_ACTIVE`).
//!
//! If this bit is set, it indicates that the context is from a thread that
//! was executing a system call in the kernel. This bit is only valid when
//! ::kMinidumpContextExceptionReporting is also set. This bit is only used on
//! Windows.
kMinidumpContextServiceActive = 0x10000000,
//! \brief Kernel-mode state reporting is desired
//! (`CONTEXT_EXCEPTION_REQUEST`).
//!
//! This bit is not used in context structures containing snapshots of thread
//! CPU context. It used when calling `GetThreadContext()` on Windows to
//! specify that kernel-mode state reporting
//! (::kMinidumpContextExceptionReporting) is desired in the returned context
//! structure.
kMinidumpContextExceptionRequest = 0x40000000,
//! \brief Kernel-mode state reporting is provided
//! (`CONTEXT_EXCEPTION_REPORTING`).
//!
//! If this bit is set, it indicates that the bits indicating how the thread
//! had entered kernel mode (::kMinidumpContextExceptionActive and
//! ::kMinidumpContextServiceActive) are valid. This bit is only used on
//! Windows.
kMinidumpContextExceptionReporting = 0x80000000,
};
//! \brief 32-bit x86-specifc flags for MinidumpContextX86::context_flags.
enum MinidumpContextX86Flags : uint32_t {
//! \brief Identifies the context structure as 32-bit x86. This is the same as
//! `CONTEXT_i386` and `CONTEXT_i486` on Windows for this architecture.
kMinidumpContextX86 = 0x00010000,
//! \brief Indicates the validity of control registers (`CONTEXT_CONTROL`).
//!
//! The `ebp`, `eip`, `cs`, `eflags`, `esp`, and `ss` fields are valid.
kMinidumpContextX86Control = kMinidumpContextX86 | 0x00000001,
//! \brief Indicates the validity of non-control integer registers
//! (`CONTEXT_INTEGER`).
//!
//! The `edi`, `esi`, `ebx`, `edx`, `ecx, and `eax` fields are valid.
kMinidumpContextX86Integer = kMinidumpContextX86 | 0x00000002,
//! \brief Indicates the validity of non-control segment registers
//! (`CONTEXT_SEGMENTS`).
//!
//! The `gs`, `fs`, `es`, and `ds` fields are valid.
kMinidumpContextX86Segment = kMinidumpContextX86 | 0x00000004,
//! \brief Indicates the validity of floating-point state
//! (`CONTEXT_FLOATING_POINT`).
//!
//! The `fsave` field is valid. The `float_save` field is included in this
//! definition, but its members have no practical use asdie from `fsave`.
kMinidumpContextX86FloatingPoint = kMinidumpContextX86 | 0x00000008,
//! \brief Indicates the validity of debug registers
//! (`CONTEXT_DEBUG_REGISTERS`).
//!
//! The `dr0` through `dr3`, `dr6`, and `dr7` fields are valid.
kMinidumpContextX86Debug = kMinidumpContextX86 | 0x00000010,
//! \brief Indicates the validity of extended registers in `fxsave` format
//! (`CONTEXT_EXTENDED_REGISTERS`).
//!
//! The `extended_registers` field is valid and contains `fxsave` data.
kMinidumpContextX86Extended = kMinidumpContextX86 | 0x00000020,
//! \brief Indicates the validity of `xsave` data (`CONTEXT_XSTATE`).
//!
//! The context contains `xsave` data. This is used with an extended context
//! structure not currently defined here.
kMinidumpContextX86Xstate = kMinidumpContextX86 | 0x00000040,
//! \brief Indicates the validity of control, integer, and segment registers.
//! (`CONTEXT_FULL`).
kMinidumpContextX86Full = kMinidumpContextX86Control |
kMinidumpContextX86Integer |
kMinidumpContextX86Segment,
//! \brief Indicates the validity of all registers except `xsave` data.
//! (`CONTEXT_ALL`).
kMinidumpContextX86All = kMinidumpContextX86Full |
kMinidumpContextX86FloatingPoint |
kMinidumpContextX86Debug |
kMinidumpContextX86Extended,
};
//! \brief A 32-bit x86 CPU context (register state) carried in a minidump file.
//!
//! This is analogous to the `CONTEXT` structure on Windows when targeting
//! 32-bit x86, and the `WOW64_CONTEXT` structure when targeting an x86-family
//! CPU, either 32- or 64-bit. This structure is used instead of `CONTEXT` or
//! `WOW64_CONTEXT` to make it available when targeting other architectures.
//!
//! \note This structure doesnt carry `dr4` or `dr5`, which are obsolete and
//! normally alias `dr6` and `dr7`, respectively. See Intel Software
//! Developers Manual, Volume 3B: System Programming, Part 2 (253669-052),
//! 17.2.2 “Debug Registers DR4 and DR5”.
struct MinidumpContextX86 {
//! \brief A bitfield composed of values of #MinidumpContextFlags and
//! #MinidumpContextX86Flags.
//!
//! This field identifies the context structure as a 32-bit x86 CPU context,
//! and indicates which other fields in the structure are valid.
uint32_t context_flags;
uint32_t dr0;
uint32_t dr1;
uint32_t dr2;
uint32_t dr3;
uint32_t dr6;
uint32_t dr7;
// CPUContextX86::Fsave has identical layout to what the x86 CONTEXT structure
// places here.
CPUContextX86::Fsave fsave;
union {
uint32_t spare_0; // As in the native x86 CONTEXT structure since Windows 8
uint32_t cr0_npx_state; // As in WOW64_CONTEXT and older SDKs x86 CONTEXT
} float_save;
uint32_t gs;
uint32_t fs;
uint32_t es;
uint32_t ds;
uint32_t edi;
uint32_t esi;
uint32_t ebx;
uint32_t edx;
uint32_t ecx;
uint32_t eax;
uint32_t ebp;
uint32_t eip;
uint32_t cs;
uint32_t eflags;
uint32_t esp;
uint32_t ss;
// CPUContextX86::Fxsave has identical layout to what the x86 CONTEXT
// structure places here.
CPUContextX86::Fxsave fxsave;
};
//! \brief x86_64-specific flags for MinidumpContextAMD64::context_flags.
enum MinidumpContextAMD64Flags : uint32_t {
//! \brief Identifies the context structure as x86_64. This is the same as
//! `CONTEXT_AMD64` on Windows for this architecture.
kMinidumpContextAMD64 = 0x00100000,
//! \brief Indicates the validity of control registers (`CONTEXT_CONTROL`).
//!
//! The `cs`, `ss`, `eflags`, `rsp`, and `rip` fields are valid.
kMinidumpContextAMD64Control = kMinidumpContextAMD64 | 0x00000001,
//! \brief Indicates the validity of non-control integer registers
//! (`CONTEXT_INTEGER`).
//!
//! The `rax`, `rcx`, `rdx`, `rbx`, `rbp`, `rsi`, `rdi`, and `r8` through
//! `r15` fields are valid.
kMinidumpContextAMD64Integer = kMinidumpContextAMD64 | 0x00000002,
//! \brief Indicates the validity of non-control segment registers
//! (`CONTEXT_SEGMENTS`).
//!
//! The `ds`, `es`, `fs`, and `gs` fields are valid.
kMinidumpContextAMD64Segment = kMinidumpContextAMD64 | 0x00000004,
//! \brief Indicates the validity of floating-point state
//! (`CONTEXT_FLOATING_POINT`).
//!
//! The `xmm0` through `xmm15` fields are valid.
kMinidumpContextAMD64FloatingPoint = kMinidumpContextAMD64 | 0x00000008,
//! \brief Indicates the validity of debug registers
//! (`CONTEXT_DEBUG_REGISTERS`).
//!
//! The `dr0` through `dr3`, `dr6`, and `dr7` fields are valid.
kMinidumpContextAMD64Debug = kMinidumpContextAMD64 | 0x00000010,
//! \brief Indicates the validity of `xsave` data (`CONTEXT_XSTATE`).
//!
//! The context contains `xsave` data. This is used with an extended context
//! structure not currently defined here.
kMinidumpContextAMD64Xstate = kMinidumpContextAMD64 | 0x00000040,
//! \brief Indicates the validity of control, integer, and floating-point
//! registers (`CONTEXT_FULL`).
kMinidumpContextAMD64Full = kMinidumpContextAMD64Control |
kMinidumpContextAMD64Integer |
kMinidumpContextAMD64FloatingPoint,
//! \brief Indicates the validity of all registers except `xsave` data
//! (`CONTEXT_ALL`).
kMinidumpContextAMD64All = kMinidumpContextAMD64Full |
kMinidumpContextAMD64Segment |
kMinidumpContextAMD64Debug,
};
//! \brief An x86_64 (AMD64) CPU context (register state) carried in a minidump
//! file.
//!
//! This is analogous to the `CONTEXT` structure on Windows when targeting
//! x86_64. This structure is used instead of `CONTEXT` to make it available
//! when targeting other architectures.
//!
//! \note This structure doesnt carry `dr4` or `dr5`, which are obsolete and
//! normally alias `dr6` and `dr7`, respectively. See Intel Software
//! Developers Manual, Volume 3B: System Programming, Part 2 (253669-052),
//! 17.2.2 “Debug Registers DR4 and DR5”.
struct alignas(16) MinidumpContextAMD64 {
//! \brief Register parameter home address.
//!
//! On Windows, this field may contain the “home” address (on-stack, in the
//! shadow area) of a parameter passed by register. This field is present for
//! convenience but is not necessarily populated, even if a corresponding
//! parameter was passed by register.
//!
//! \{
uint64_t p1_home;
uint64_t p2_home;
uint64_t p3_home;
uint64_t p4_home;
uint64_t p5_home;
uint64_t p6_home;
//! \}
//! \brief A bitfield composed of values of #MinidumpContextFlags and
//! #MinidumpContextAMD64Flags.
//!
//! This field identifies the context structure as an x86_64 CPU context, and
//! indicates which other fields in the structure are valid.
uint32_t context_flags;
uint32_t mx_csr;
uint16_t cs;
uint16_t ds;
uint16_t es;
uint16_t fs;
uint16_t gs;
uint16_t ss;
uint32_t eflags;
uint64_t dr0;
uint64_t dr1;
uint64_t dr2;
uint64_t dr3;
uint64_t dr6;
uint64_t dr7;
uint64_t rax;
uint64_t rcx;
uint64_t rdx;
uint64_t rbx;
uint64_t rsp;
uint64_t rbp;
uint64_t rsi;
uint64_t rdi;
uint64_t r8;
uint64_t r9;
uint64_t r10;
uint64_t r11;
uint64_t r12;
uint64_t r13;
uint64_t r14;
uint64_t r15;
uint64_t rip;
// CPUContextX86_64::Fxsave has identical layout to what the x86_64 CONTEXT
// structure places here.
CPUContextX86_64::Fxsave fxsave;
uint128_struct vector_register[26];
uint64_t vector_control;
//! \brief Model-specific debug extension register.
//!
//! See Intel Software Developers Manual, Volume 3B: System Programming, Part
//! 2 (253669-051), 17.4 “Last Branch, Interrupt, and Exception Recording
//! Overview”, and AMD Architecture Programmers Manual, Volume 2: System
//! Programming (24593-3.24), 13.1.6 “Control-Transfer Breakpoint Features”.
//!
//! \{
uint64_t debug_control;
uint64_t last_branch_to_rip;
uint64_t last_branch_from_rip;
uint64_t last_exception_to_rip;
uint64_t last_exception_from_rip;
//! \}
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_H_
@@ -0,0 +1,160 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_WRITER_H_
#include <sys/types.h>
#include <memory>
#include "base/macros.h"
#include "minidump/minidump_context.h"
#include "minidump/minidump_writable.h"
namespace crashpad {
struct CPUContext;
struct CPUContextX86;
struct CPUContextX86_64;
//! \brief The base class for writers of CPU context structures in minidump
//! files.
class MinidumpContextWriter : public internal::MinidumpWritable {
public:
~MinidumpContextWriter() override;
//! \brief Creates a MinidumpContextWriter based on \a context_snapshot.
//!
//! \param[in] context_snapshot The context snapshot to use as source data.
//!
//! \return A MinidumpContextWriter subclass, such as MinidumpContextWriterX86
//! or MinidumpContextWriterAMD64, appropriate to the CPU type of \a
//! context_snapshot. The returned object is initialized using the source
//! data in \a context_snapshot. If \a context_snapshot is an unknown CPU
//! types context, logs a message and returns `nullptr`.
static std::unique_ptr<MinidumpContextWriter> CreateFromSnapshot(
const CPUContext* context_snapshot);
protected:
MinidumpContextWriter() : MinidumpWritable() {}
//! \brief Returns the size of the context structure that this object will
//! write.
//!
//! \note This method will only be called in #kStateFrozen or a subsequent
//! state.
virtual size_t ContextSize() const = 0;
// MinidumpWritable:
size_t SizeOfObject() final;
private:
DISALLOW_COPY_AND_ASSIGN(MinidumpContextWriter);
};
//! \brief The writer for a MinidumpContextX86 structure in a minidump file.
class MinidumpContextX86Writer final : public MinidumpContextWriter {
public:
MinidumpContextX86Writer();
~MinidumpContextX86Writer() override;
//! \brief Initializes the MinidumpContextX86 based on \a context_snapshot.
//!
//! \param[in] context_snapshot The context snapshot to use as source data.
//!
//! \note Valid in #kStateMutable. No mutation of context() may be done before
//! calling this method, and it is not normally necessary to alter
//! context() after calling this method.
void InitializeFromSnapshot(const CPUContextX86* context_snapshot);
//! \brief Returns a pointer to the context structure that this object will
//! write.
//!
//! \attention This returns a non-`const` pointer to this objects private
//! data so that a caller can populate the context structure directly.
//! This is done because providing setter interfaces to each field in the
//! context structure would be unwieldy and cumbersome. Care must be taken
//! to populate the context structure correctly. The context structure
//! must only be modified while this object is in the #kStateMutable
//! state.
MinidumpContextX86* context() { return &context_; }
protected:
// MinidumpWritable:
bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpContextWriter:
size_t ContextSize() const override;
private:
MinidumpContextX86 context_;
DISALLOW_COPY_AND_ASSIGN(MinidumpContextX86Writer);
};
//! \brief The writer for a MinidumpContextAMD64 structure in a minidump file.
class MinidumpContextAMD64Writer final : public MinidumpContextWriter {
public:
MinidumpContextAMD64Writer();
~MinidumpContextAMD64Writer() override;
// Ensure proper alignment of heap-allocated objects. This should not be
// necessary in C++17.
static void* operator new(size_t size);
static void operator delete(void* ptr);
// Prevent unaligned heap-allocated arrays. Provisions could be made to allow
// these if necessary, but there is currently no use for them.
static void* operator new[](size_t size) = delete;
static void operator delete[](void* ptr) = delete;
//! \brief Initializes the MinidumpContextAMD64 based on \a context_snapshot.
//!
//! \param[in] context_snapshot The context snapshot to use as source data.
//!
//! \note Valid in #kStateMutable. No mutation of context() may be done before
//! calling this method, and it is not normally necessary to alter
//! context() after calling this method.
void InitializeFromSnapshot(const CPUContextX86_64* context_snapshot);
//! \brief Returns a pointer to the context structure that this object will
//! write.
//!
//! \attention This returns a non-`const` pointer to this objects private
//! data so that a caller can populate the context structure directly.
//! This is done because providing setter interfaces to each field in the
//! context structure would be unwieldy and cumbersome. Care must be taken
//! to populate the context structure correctly. The context structure
//! must only be modified while this object is in the #kStateMutable
//! state.
MinidumpContextAMD64* context() { return &context_; }
protected:
// MinidumpWritable:
size_t Alignment() override;
bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpContextWriter:
size_t ContextSize() const override;
private:
MinidumpContextAMD64 context_;
DISALLOW_COPY_AND_ASSIGN(MinidumpContextAMD64Writer);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_WRITER_H_
@@ -0,0 +1,114 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_CRASHPAD_INFO_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_CRASHPAD_INFO_WRITER_H_
#include <sys/types.h>
#include <memory>
#include <vector>
#include "base/macros.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_stream_writer.h"
#include "util/misc/uuid.h"
namespace crashpad {
class MinidumpModuleCrashpadInfoListWriter;
class MinidumpSimpleStringDictionaryWriter;
class ProcessSnapshot;
//! \brief The writer for a MinidumpCrashpadInfo stream in a minidump file.
class MinidumpCrashpadInfoWriter final : public internal::MinidumpStreamWriter {
public:
MinidumpCrashpadInfoWriter();
~MinidumpCrashpadInfoWriter() override;
//! \brief Initializes MinidumpCrashpadInfo based on \a process_snapshot.
//!
//! This method may add additional structures to the minidump file as children
//! of the MinidumpCrashpadInfo stream. To do so, it may obtain other
//! snapshot information from \a process_snapshot, such as a list of
//! ModuleSnapshot objects used to initialize
//! MinidumpCrashpadInfo::module_list. Only data that is considered useful
//! will be included. For module information, usefulness is determined by
//! MinidumpModuleCrashpadInfoListWriter::IsUseful().
//!
//! \param[in] process_snapshot The process snapshot to use as source data.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromSnapshot(const ProcessSnapshot* process_snapshot);
//! \brief Sets MinidumpCrashpadInfo::report_id.
void SetReportID(const UUID& report_id);
//! \brief Sets MinidumpCrashpadInfo::client_id.
void SetClientID(const UUID& client_id);
//! \brief Arranges for MinidumpCrashpadInfo::simple_annotations to point to
//! the MinidumpSimpleStringDictionaryWriter object to be written by \a
//! simple_annotations.
//!
//! This object takes ownership of \a simple_annotations and becomes its
//! parent in the overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void SetSimpleAnnotations(
std::unique_ptr<MinidumpSimpleStringDictionaryWriter> simple_annotations);
//! \brief Arranges for MinidumpCrashpadInfo::module_list to point to the
//! MinidumpModuleCrashpadInfoList object to be written by \a
//! module_list.
//!
//! This object takes ownership of \a module_list and becomes its parent in
//! the overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void SetModuleList(
std::unique_ptr<MinidumpModuleCrashpadInfoListWriter> module_list);
//! \brief Determines whether the object is useful.
//!
//! A useful object is one that carries data that makes a meaningful
//! contribution to a minidump file. An object carrying children would be
//! considered useful.
//!
//! \return `true` if the object is useful, `false` otherwise.
bool IsUseful() const;
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpStreamWriter:
MinidumpStreamType StreamType() const override;
private:
MinidumpCrashpadInfo crashpad_info_;
std::unique_ptr<MinidumpSimpleStringDictionaryWriter> simple_annotations_;
std::unique_ptr<MinidumpModuleCrashpadInfoListWriter> module_list_;
DISALLOW_COPY_AND_ASSIGN(MinidumpCrashpadInfoWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_CRASHPAD_INFO_WRITER_H_
@@ -0,0 +1,126 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_EXCEPTION_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_EXCEPTION_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include <stdint.h>
#include <sys/types.h>
#include <memory>
#include <vector>
#include "base/macros.h"
#include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_thread_id_map.h"
namespace crashpad {
class ExceptionSnapshot;
class MinidumpContextWriter;
class MinidumpMemoryListWriter;
//! \brief The writer for a MINIDUMP_EXCEPTION_STREAM stream in a minidump file.
class MinidumpExceptionWriter final : public internal::MinidumpStreamWriter {
public:
MinidumpExceptionWriter();
~MinidumpExceptionWriter() override;
//! \brief Initializes the MINIDUMP_EXCEPTION_STREAM based on \a
//! exception_snapshot.
//!
//! \param[in] exception_snapshot The exception snapshot to use as source
//! data.
//! \param[in] thread_id_map A MinidumpThreadIDMap to be consulted to
//! determine the 32-bit minidump thread ID to use for the thread
//! identified by \a exception_snapshot.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromSnapshot(const ExceptionSnapshot* exception_snapshot,
const MinidumpThreadIDMap& thread_id_map);
//! \brief Arranges for MINIDUMP_EXCEPTION_STREAM::ThreadContext to point to
//! the CPU context to be written by \a context.
//!
//! A context is required in all MINIDUMP_EXCEPTION_STREAM objects.
//!
//! This object takes ownership of \a context and becomes its parent in the
//! overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void SetContext(std::unique_ptr<MinidumpContextWriter> context);
//! \brief Sets MINIDUMP_EXCEPTION_STREAM::ThreadId.
void SetThreadID(uint32_t thread_id) { exception_.ThreadId = thread_id; }
//! \brief Sets MINIDUMP_EXCEPTION::ExceptionCode.
void SetExceptionCode(uint32_t exception_code) {
exception_.ExceptionRecord.ExceptionCode = exception_code;
}
//! \brief Sets MINIDUMP_EXCEPTION::ExceptionFlags.
void SetExceptionFlags(uint32_t exception_flags) {
exception_.ExceptionRecord.ExceptionFlags = exception_flags;
}
//! \brief Sets MINIDUMP_EXCEPTION::ExceptionRecord.
void SetExceptionRecord(uint64_t exception_record) {
exception_.ExceptionRecord.ExceptionRecord = exception_record;
}
//! \brief Sets MINIDUMP_EXCEPTION::ExceptionAddress.
void SetExceptionAddress(uint64_t exception_address) {
exception_.ExceptionRecord.ExceptionAddress = exception_address;
}
//! \brief Sets MINIDUMP_EXCEPTION::ExceptionInformation and
//! MINIDUMP_EXCEPTION::NumberParameters.
//!
//! MINIDUMP_EXCEPTION::NumberParameters is set to the number of elements in
//! \a exception_information. The elements of
//! MINIDUMP_EXCEPTION::ExceptionInformation are set to the elements of \a
//! exception_information. Unused elements in
//! MINIDUMP_EXCEPTION::ExceptionInformation are set to `0`.
//!
//! \a exception_information must have no more than
//! #EXCEPTION_MAXIMUM_PARAMETERS elements.
//!
//! \note Valid in #kStateMutable.
void SetExceptionInformation(
const std::vector<uint64_t>& exception_information);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpStreamWriter:
MinidumpStreamType StreamType() const override;
private:
MINIDUMP_EXCEPTION_STREAM exception_;
std::unique_ptr<MinidumpContextWriter> context_;
DISALLOW_COPY_AND_ASSIGN(MinidumpExceptionWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_EXCEPTION_WRITER_H_
@@ -0,0 +1,497 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_EXTENSIONS_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_EXTENSIONS_H_
#include <windows.h>
#include <dbghelp.h>
#include <stdint.h>
#include <winnt.h>
#include "base/compiler_specific.h"
#include "build/build_config.h"
#include "util/misc/pdb_structures.h"
#include "util/misc/uuid.h"
// C4200 is "nonstandard extension used : zero-sized array in struct/union".
// We would like to globally disable this warning, but unfortunately, the
// compiler is buggy and only supports disabling it with a pragma, so we can't
// disable it with other silly warnings in build/common.gypi. See:
// https://connect.microsoft.com/VisualStudio/feedback/details/1114440
MSVC_PUSH_DISABLE_WARNING(4200);
#if defined(COMPILER_MSVC)
#define PACKED
#pragma pack(push, 1)
#else
#define PACKED __attribute__((packed))
#endif // COMPILER_MSVC
namespace crashpad {
//! \brief Minidump stream type values for MINIDUMP_DIRECTORY::StreamType. Each
//! stream structure has a corresponding stream type value to identify it.
//!
//! \sa MINIDUMP_STREAM_TYPE
enum MinidumpStreamType : uint32_t {
//! \brief The stream type for MINIDUMP_THREAD_LIST.
//!
//! \sa ThreadListStream
kMinidumpStreamTypeThreadList = ThreadListStream,
//! \brief The stream type for MINIDUMP_MODULE_LIST.
//!
//! \sa ModuleListStream
kMinidumpStreamTypeModuleList = ModuleListStream,
//! \brief The stream type for MINIDUMP_MEMORY_LIST.
//!
//! \sa MemoryListStream
kMinidumpStreamTypeMemoryList = MemoryListStream,
//! \brief The stream type for MINIDUMP_EXCEPTION_STREAM.
//!
//! \sa ExceptionStream
kMinidumpStreamTypeException = ExceptionStream,
//! \brief The stream type for MINIDUMP_SYSTEM_INFO.
//!
//! \sa SystemInfoStream
kMinidumpStreamTypeSystemInfo = SystemInfoStream,
//! \brief The stream type for MINIDUMP_HANDLE_DATA_STREAM.
//!
//! \sa HandleDataStream
kMinidumpStreamTypeHandleData = HandleDataStream,
//! \brief The stream type for MINIDUMP_UNLOADED_MODULE_LIST.
//!
//! \sa UnloadedModuleListStream
kMinidumpStreamTypeUnloadedModuleList = UnloadedModuleListStream,
//! \brief The stream type for MINIDUMP_MISC_INFO, MINIDUMP_MISC_INFO_2,
//! MINIDUMP_MISC_INFO_3, and MINIDUMP_MISC_INFO_4.
//!
//! \sa MiscInfoStream
kMinidumpStreamTypeMiscInfo = MiscInfoStream,
//! \brief The stream type for MINIDUMP_MEMORY_INFO_LIST.
//!
//! \sa MemoryInfoListStream
kMinidumpStreamTypeMemoryInfoList = MemoryInfoListStream,
// 0x4350 = "CP"
//! \brief The stream type for MinidumpCrashpadInfo.
kMinidumpStreamTypeCrashpadInfo = 0x43500001,
};
//! \brief A variable-length UTF-8-encoded string carried within a minidump
//! file.
//!
//! \sa MINIDUMP_STRING
struct ALIGNAS(4) PACKED MinidumpUTF8String {
// The field names do not conform to typical style, they match the names used
// in MINIDUMP_STRING. This makes it easier to operate on MINIDUMP_STRING (for
// UTF-16 strings) and MinidumpUTF8String using templates.
//! \brief The length of the #Buffer field in bytes, not including the `NUL`
//! terminator.
//!
//! \note This field is interpreted as a byte count, not a count of Unicode
//! code points.
uint32_t Length;
//! \brief The string, encoded in UTF-8, and terminated with a `NUL` byte.
uint8_t Buffer[0];
};
//! \brief A variable-length array of bytes carried within a minidump file.
//! The data have no intrinsic type and should be interpreted according
//! to their referencing context.
struct ALIGNAS(4) PACKED MinidumpByteArray {
//! \brief The length of the #data field.
uint32_t length;
//! \brief The bytes of data.
uint8_t data[0];
};
//! \brief CPU type values for MINIDUMP_SYSTEM_INFO::ProcessorArchitecture.
//!
//! \sa \ref PROCESSOR_ARCHITECTURE_x "PROCESSOR_ARCHITECTURE_*"
enum MinidumpCPUArchitecture : uint16_t {
//! \brief 32-bit x86.
//!
//! These systems identify their CPUs generically as “x86” or “ia32”, or with
//! more specific names such as “i386”, “i486”, “i586”, and “i686”.
kMinidumpCPUArchitectureX86 = PROCESSOR_ARCHITECTURE_INTEL,
kMinidumpCPUArchitectureMIPS = PROCESSOR_ARCHITECTURE_MIPS,
kMinidumpCPUArchitectureAlpha = PROCESSOR_ARCHITECTURE_ALPHA,
//! \brief 32-bit PowerPC.
//!
//! These systems identify their CPUs generically as “ppc”, or with more
//! specific names such as “ppc6xx”, “ppc7xx”, and “ppc74xx”.
kMinidumpCPUArchitecturePPC = PROCESSOR_ARCHITECTURE_PPC,
kMinidumpCPUArchitectureSHx = PROCESSOR_ARCHITECTURE_SHX,
//! \brief 32-bit ARM.
//!
//! These systems identify their CPUs generically as “arm”, or with more
//! specific names such as “armv6” and “armv7”.
kMinidumpCPUArchitectureARM = PROCESSOR_ARCHITECTURE_ARM,
kMinidumpCPUArchitectureIA64 = PROCESSOR_ARCHITECTURE_IA64,
kMinidumpCPUArchitectureAlpha64 = PROCESSOR_ARCHITECTURE_ALPHA64,
kMinidumpCPUArchitectureMSIL = PROCESSOR_ARCHITECTURE_MSIL,
//! \brief 64-bit x86.
//!
//! These systems identify their CPUs as “x86_64”, “amd64”, or “x64”.
kMinidumpCPUArchitectureAMD64 = PROCESSOR_ARCHITECTURE_AMD64,
//! \brief A 32-bit x86 process running on IA-64 (Itanium).
//!
//! \note This value is not used in minidump files for 32-bit x86 processes
//! running on a 64-bit-capable x86 CPU and operating system. In that
//! configuration, #kMinidumpCPUArchitectureX86 is used instead.
kMinidumpCPUArchitectureX86Win64 = PROCESSOR_ARCHITECTURE_IA32_ON_WIN64,
kMinidumpCPUArchitectureNeutral = PROCESSOR_ARCHITECTURE_NEUTRAL,
//! \brief 64-bit ARM.
//!
//! These systems identify their CPUs generically as “arm64” or “aarch64”, or
//! with more specific names such as “armv8”.
//!
//! \sa #kMinidumpCPUArchitectureARM64Breakpad
kMinidumpCPUArchitectureARM64 = PROCESSOR_ARCHITECTURE_ARM64,
kMinidumpCPUArchitectureARM32Win64 = PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64,
kMinidumpCPUArchitectureSPARC = 0x8001,
//! \brief 64-bit PowerPC.
//!
//! These systems identify their CPUs generically as “ppc64”, or with more
//! specific names such as “ppc970”.
kMinidumpCPUArchitecturePPC64 = 0x8002,
//! \brief Used by Breakpad for 64-bit ARM.
//!
//! \deprecated Use #kMinidumpCPUArchitectureARM64 instead.
kMinidumpCPUArchitectureARM64Breakpad = 0x8003,
//! \brief Unknown CPU architecture.
kMinidumpCPUArchitectureUnknown = PROCESSOR_ARCHITECTURE_UNKNOWN,
};
//! \brief Operating system type values for MINIDUMP_SYSTEM_INFO::ProductType.
//!
//! \sa \ref VER_NT_x "VER_NT_*"
enum MinidumpOSType : uint8_t {
//! \brief A “desktop” or “workstation” system.
kMinidumpOSTypeWorkstation = VER_NT_WORKSTATION,
//! \brief A “domain controller” system. Windows-specific.
kMinidumpOSTypeDomainController = VER_NT_DOMAIN_CONTROLLER,
//! \brief A “server” system.
kMinidumpOSTypeServer = VER_NT_SERVER,
};
//! \brief Operating system family values for MINIDUMP_SYSTEM_INFO::PlatformId.
//!
//! \sa \ref VER_PLATFORM_x "VER_PLATFORM_*"
enum MinidumpOS : uint32_t {
//! \brief Windows 3.1.
kMinidumpOSWin32s = VER_PLATFORM_WIN32s,
//! \brief Windows 95, Windows 98, and Windows Me.
kMinidumpOSWin32Windows = VER_PLATFORM_WIN32_WINDOWS,
//! \brief Windows NT, Windows 2000, and later.
kMinidumpOSWin32NT = VER_PLATFORM_WIN32_NT,
kMinidumpOSUnix = 0x8000,
//! \brief macOS, Darwin for traditional systems.
kMinidumpOSMacOSX = 0x8101,
//! \brief iOS, Darwin for mobile devices.
kMinidumpOSiOS = 0x8102,
//! \brief Linux, not including Android.
kMinidumpOSLinux = 0x8201,
kMinidumpOSSolaris = 0x8202,
//! \brief Android.
kMinidumpOSAndroid = 0x8203,
kMinidumpOSLegacy = 0x8204,
//! \brief Native Client (NaCl).
kMinidumpOSNaCl = 0x8205,
//! \brief Unknown operating system.
kMinidumpOSUnknown = 0xffffffff,
};
//! \brief A list of ::RVA pointers.
struct ALIGNAS(4) PACKED MinidumpRVAList {
//! \brief The number of children present in the #children array.
uint32_t count;
//! \brief Pointers to other structures in the minidump file.
RVA children[0];
};
//! \brief A key-value pair.
struct ALIGNAS(4) PACKED MinidumpSimpleStringDictionaryEntry {
//! \brief ::RVA of a MinidumpUTF8String containing the key of a key-value
//! pair.
RVA key;
//! \brief ::RVA of a MinidumpUTF8String containing the value of a key-value
//! pair.
RVA value;
};
//! \brief A list of key-value pairs.
struct ALIGNAS(4) PACKED MinidumpSimpleStringDictionary {
//! \brief The number of key-value pairs present.
uint32_t count;
//! \brief A list of MinidumpSimpleStringDictionaryEntry entries.
MinidumpSimpleStringDictionaryEntry entries[0];
};
//! \brief A typed annotation object.
struct ALIGNAS(4) PACKED MinidumpAnnotation {
//! \brief ::RVA of a MinidumpUTF8String containing the name of the
//! annotation.
RVA name;
//! \brief The type of data stored in the \a value of the annotation. This
//! may correspond to an \a Annotation::Type or it may be user-defined.
uint16_t type;
//! \brief This field is always `0`.
uint16_t reserved;
//! \brief ::RVA of a MinidumpByteArray to the data for the annotation.
RVA value;
};
//! \brief A list of annotation objects.
struct ALIGNAS(4) PACKED MinidumpAnnotationList {
//! \brief The number of annotation objects present.
uint32_t count;
//! \brief A list of MinidumpAnnotation objects.
MinidumpAnnotation objects[0];
};
//! \brief Additional Crashpad-specific information about a module carried
//! within a minidump file.
//!
//! This structure augments the information provided by MINIDUMP_MODULE. The
//! minidump file must contain a module list stream
//! (::kMinidumpStreamTypeModuleList) in order for this structure to appear.
//!
//! This structure is versioned. When changing this structure, leave the
//! existing structure intact so that earlier parsers will be able to understand
//! the fields they are aware of, and make additions at the end of the
//! structure. Revise #kVersion and document each fields validity based on
//! #version, so that newer parsers will be able to determine whether the added
//! fields are valid or not.
//!
//! \sa MinidumpModuleCrashpadInfoList
struct ALIGNAS(4) PACKED MinidumpModuleCrashpadInfo {
//! \brief The structures currently-defined version number.
//!
//! \sa version
static constexpr uint32_t kVersion = 1;
//! \brief The structures version number.
//!
//! Readers can use this field to determine which other fields in the
//! structure are valid. Upon encountering a value greater than #kVersion, a
//! reader should assume that the structures layout is compatible with the
//! structure defined as having value #kVersion.
//!
//! Writers may produce values less than #kVersion in this field if there is
//! no need for any fields present in later versions.
uint32_t version;
//! \brief A MinidumpRVAList pointing to MinidumpUTF8String objects. The
//! module controls the data that appears here.
//!
//! These strings correspond to ModuleSnapshot::AnnotationsVector() and do not
//! duplicate anything in #simple_annotations or #annotation_objects.
//!
//! This field is present when #version is at least `1`.
MINIDUMP_LOCATION_DESCRIPTOR list_annotations;
//! \brief A MinidumpSimpleStringDictionary pointing to strings interpreted as
//! key-value pairs. The module controls the data that appears here.
//!
//! These key-value pairs correspond to
//! ModuleSnapshot::AnnotationsSimpleMap() and do not duplicate anything in
//! #list_annotations or #annotation_objects.
//!
//! This field is present when #version is at least `1`.
MINIDUMP_LOCATION_DESCRIPTOR simple_annotations;
//! \brief A MinidumpAnnotationList object containing the annotation objects
//! stored within the module. The module controls the data that appears
//! here.
//!
//! These key-value pairs correspond to ModuleSnapshot::AnnotationObjects()
//! and do not duplicate anything in #list_annotations or #simple_annotations.
//!
//! This field may be present when #version is at least `1`.
MINIDUMP_LOCATION_DESCRIPTOR annotation_objects;
};
//! \brief A link between a MINIDUMP_MODULE structure and additional
//! Crashpad-specific information about a module carried within a minidump
//! file.
struct ALIGNAS(4) PACKED MinidumpModuleCrashpadInfoLink {
//! \brief A link to a MINIDUMP_MODULE structure in the module list stream.
//!
//! This field is an index into MINIDUMP_MODULE_LIST::Modules. This fields
//! value must be in the range of MINIDUMP_MODULE_LIST::NumberOfEntries.
uint32_t minidump_module_list_index;
//! \brief A link to a MinidumpModuleCrashpadInfo structure.
//!
//! MinidumpModuleCrashpadInfo structures are accessed indirectly through
//! MINIDUMP_LOCATION_DESCRIPTOR pointers to allow for future growth of the
//! MinidumpModuleCrashpadInfo structure.
MINIDUMP_LOCATION_DESCRIPTOR location;
};
//! \brief Additional Crashpad-specific information about modules carried within
//! a minidump file.
//!
//! This structure augments the information provided by
//! MINIDUMP_MODULE_LIST. The minidump file must contain a module list stream
//! (::kMinidumpStreamTypeModuleList) in order for this structure to appear.
//!
//! MinidumpModuleCrashpadInfoList::count may be less than the value of
//! MINIDUMP_MODULE_LIST::NumberOfModules because not every MINIDUMP_MODULE
//! structure carried within the minidump file will necessarily have
//! Crashpad-specific information provided by a MinidumpModuleCrashpadInfo
//! structure.
struct ALIGNAS(4) PACKED MinidumpModuleCrashpadInfoList {
//! \brief The number of children present in the #modules array.
uint32_t count;
//! \brief Crashpad-specific information about modules, along with links to
//! MINIDUMP_MODULE structures that contain module information
//! traditionally carried within minidump files.
MinidumpModuleCrashpadInfoLink modules[0];
};
//! \brief Additional Crashpad-specific information carried within a minidump
//! file.
//!
//! This structure is versioned. When changing this structure, leave the
//! existing structure intact so that earlier parsers will be able to understand
//! the fields they are aware of, and make additions at the end of the
//! structure. Revise #kVersion and document each fields validity based on
//! #version, so that newer parsers will be able to determine whether the added
//! fields are valid or not.
struct ALIGNAS(4) PACKED MinidumpCrashpadInfo {
// UUID has a constructor, which makes it non-POD, which makes this structure
// non-POD. In order for the default constructor to zero-initialize other
// members, an explicit constructor must be provided.
MinidumpCrashpadInfo()
: version(),
report_id(),
client_id(),
simple_annotations(),
module_list() {
}
//! \brief The structures currently-defined version number.
//!
//! \sa version
static constexpr uint32_t kVersion = 1;
//! \brief The structures version number.
//!
//! Readers can use this field to determine which other fields in the
//! structure are valid. Upon encountering a value greater than #kVersion, a
//! reader should assume that the structures layout is compatible with the
//! structure defined as having value #kVersion.
//!
//! Writers may produce values less than #kVersion in this field if there is
//! no need for any fields present in later versions.
uint32_t version;
//! \brief A %UUID identifying an individual crash report.
//!
//! This provides a stable identifier for a crash even as the report is
//! converted to different formats, provided that all formats support storing
//! a crash report ID.
//!
//! If no identifier is available, this field will contain zeroes.
//!
//! This field is present when #version is at least `1`.
UUID report_id;
//! \brief A %UUID identifying the client that crashed.
//!
//! Client identification is within the scope of the application, but it is
//! expected that the identifier will be unique for an instance of Crashpad
//! monitoring an application or set of applications for a user. The
//! identifier shall remain stable over time.
//!
//! If no identifier is available, this field will contain zeroes.
//!
//! This field is present when #version is at least `1`.
UUID client_id;
//! \brief A MinidumpSimpleStringDictionary pointing to strings interpreted as
//! key-value pairs.
//!
//! These key-value pairs correspond to
//! ProcessSnapshot::AnnotationsSimpleMap().
//!
//! This field is present when #version is at least `1`.
MINIDUMP_LOCATION_DESCRIPTOR simple_annotations;
//! \brief A pointer to a MinidumpModuleCrashpadInfoList structure.
//!
//! This field is present when #version is at least `1`.
MINIDUMP_LOCATION_DESCRIPTOR module_list;
};
#if defined(COMPILER_MSVC)
#pragma pack(pop)
#endif // COMPILER_MSVC
#undef PACKED
MSVC_POP_WARNING(); // C4200
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_EXTENSIONS_H_
@@ -0,0 +1,157 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_FILE_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_FILE_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include <sys/types.h>
#include <memory>
#include <set>
#include <vector>
#include "base/macros.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_writable.h"
#include "util/file/file_io.h"
namespace crashpad {
class ProcessSnapshot;
class MinidumpUserExtensionStreamDataSource;
//! \brief The root-level object in a minidump file.
//!
//! This object writes a MINIDUMP_HEADER and list of MINIDUMP_DIRECTORY entries
//! to a minidump file.
class MinidumpFileWriter final : public internal::MinidumpWritable {
public:
MinidumpFileWriter();
~MinidumpFileWriter() override;
//! \brief Initializes the MinidumpFileWriter and populates it with
//! appropriate child streams based on \a process_snapshot.
//!
//! This method will add additional streams to the minidump file as children
//! of the MinidumpFileWriter object and as pointees of the top-level
//! MINIDUMP_DIRECTORY. To do so, it will obtain other snapshot information
//! from \a process_snapshot, such as a SystemSnapshot, lists of
//! ThreadSnapshot and ModuleSnapshot objects, and, if available, an
//! ExceptionSnapshot.
//!
//! The streams are added in the order that they are expected to be most
//! useful to minidump readers, to improve data locality and minimize seeking.
//! The streams are added in this order:
//! - kMinidumpStreamTypeSystemInfo
//! - kMinidumpStreamTypeMiscInfo
//! - kMinidumpStreamTypeThreadList
//! - kMinidumpStreamTypeException (if present)
//! - kMinidumpStreamTypeModuleList
//! - kMinidumpStreamTypeUnloadedModuleList (if present)
//! - kMinidumpStreamTypeCrashpadInfo (if present)
//! - kMinidumpStreamTypeMemoryInfoList (if present)
//! - kMinidumpStreamTypeHandleData (if present)
//! - User streams (if present)
//! - kMinidumpStreamTypeMemoryList
//!
//! \param[in] process_snapshot The process snapshot to use as source data.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromSnapshot(const ProcessSnapshot* process_snapshot);
//! \brief Sets MINIDUMP_HEADER::Timestamp.
//!
//! \note Valid in #kStateMutable.
void SetTimestamp(time_t timestamp);
//! \brief Adds a stream to the minidump file and arranges for a
//! MINIDUMP_DIRECTORY entry to point to it.
//!
//! This object takes ownership of \a stream and becomes its parent in the
//! overall tree of internal::MinidumpWritable objects.
//!
//! At most one object of each stream type (as obtained from
//! internal::MinidumpStreamWriter::StreamType()) may be added to a
//! MinidumpFileWriter object. If an attempt is made to add a stream whose
//! type matches an existing streams type, this method discards the new
//! stream.
//!
//! \note Valid in #kStateMutable.
//!
//! \return `true` on success. `false` on failure, as occurs when an attempt
//! is made to add a stream whose type matches an existing streams type,
//! with a message logged.
bool AddStream(std::unique_ptr<internal::MinidumpStreamWriter> stream);
//! \brief Adds a user extension stream to the minidump file and arranges for
//! a MINIDUMP_DIRECTORY entry to point to it.
//!
//! This object takes ownership of \a user_extension_stream_data.
//!
//! At most one object of each stream type (as obtained from
//! internal::MinidumpStreamWriter::StreamType()) may be added to a
//! MinidumpFileWriter object. If an attempt is made to add a stream whose
//! type matches an existing streams type, this method discards the new
//! stream.
//!
//! \param[in] user_extension_stream_data The stream data to add to the
//! minidump file. Note that the buffer this object points to must be valid
//! through WriteEverything().
//!
//! \note Valid in #kStateMutable.
//!
//! \return `true` on success. `false` on failure, as occurs when an attempt
//! is made to add a stream whose type matches an existing streams type,
//! with a message logged.
bool AddUserExtensionStream(
std::unique_ptr<MinidumpUserExtensionStreamDataSource>
user_extension_stream_data);
// MinidumpWritable:
//! \copydoc internal::MinidumpWritable::WriteEverything()
//!
//! This method does not initially write the final value for
//! MINIDUMP_HEADER::Signature. After all child objects have been written, it
//! rewinds to the beginning of the file and writes the correct value for this
//! field. This prevents incompletely-written minidump files from being
//! mistaken for valid ones.
bool WriteEverything(FileWriterInterface* file_writer) override;
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WillWriteAtOffsetImpl(FileOffset offset) override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
MINIDUMP_HEADER header_;
std::vector<std::unique_ptr<internal::MinidumpStreamWriter>> streams_;
// Protects against multiple streams with the same ID being added.
std::set<MinidumpStreamType> stream_types_;
DISALLOW_COPY_AND_ASSIGN(MinidumpFileWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_WRITER_H_
@@ -0,0 +1,77 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_HANDLE_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_HANDLE_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include <sys/types.h>
#include <map>
#include <string>
#include <vector>
#include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_string_writer.h"
#include "minidump/minidump_writable.h"
#include "snapshot/handle_snapshot.h"
namespace crashpad {
//! \brief The writer for a MINIDUMP_HANDLE_DATA_STREAM stream in a minidump
//! and its contained MINIDUMP_HANDLE_DESCRIPTOR s.
//!
//! As we currently do not track any data beyond what MINIDUMP_HANDLE_DESCRIPTOR
//! supports, we only write that type of record rather than the newer
//! MINIDUMP_HANDLE_DESCRIPTOR_2.
//!
//! Note that this writer writes both the header (MINIDUMP_HANDLE_DATA_STREAM)
//! and the list of objects (MINIDUMP_HANDLE_DESCRIPTOR), which is different
//! from some of the other list writers.
class MinidumpHandleDataWriter final : public internal::MinidumpStreamWriter {
public:
MinidumpHandleDataWriter();
~MinidumpHandleDataWriter() override;
//! \brief Adds a MINIDUMP_HANDLE_DESCRIPTOR for each handle in \a
//! handle_snapshot to the MINIDUMP_HANDLE_DATA_STREAM.
//!
//! \param[in] handle_snapshots The handle snapshots to use as source data.
//!
//! \note Valid in #kStateMutable.
void InitializeFromSnapshot(
const std::vector<HandleSnapshot>& handle_snapshots);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpStreamWriter:
MinidumpStreamType StreamType() const override;
private:
MINIDUMP_HANDLE_DATA_STREAM handle_data_stream_base_;
std::vector<MINIDUMP_HANDLE_DESCRIPTOR> handle_descriptors_;
std::map<std::string, internal::MinidumpUTF16StringWriter*> strings_;
DISALLOW_COPY_AND_ASSIGN(MinidumpHandleDataWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_HANDLE_WRITER_H_
@@ -0,0 +1,72 @@
// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_MEMORY_INFO_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_MEMORY_INFO_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include <stdint.h>
#include <sys/types.h>
#include <vector>
#include "base/macros.h"
#include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_writable.h"
namespace crashpad {
class MemoryMapRegionSnapshot;
class MinidumpContextWriter;
class MinidumpMemoryListWriter;
class MinidumpMemoryWriter;
//! \brief The writer for a MINIDUMP_MEMORY_INFO_LIST stream in a minidump file,
//! containing a list of MINIDUMP_MEMORY_INFO objects.
class MinidumpMemoryInfoListWriter final
: public internal::MinidumpStreamWriter {
public:
MinidumpMemoryInfoListWriter();
~MinidumpMemoryInfoListWriter() override;
//! \brief Initializes a MINIDUMP_MEMORY_INFO_LIST based on \a memory_map.
//!
//! \param[in] memory_map The vector of memory map region snapshots to use as
//! source data.
//!
//! \note Valid in #kStateMutable.
void InitializeFromSnapshot(
const std::vector<const MemoryMapRegionSnapshot*>& memory_map);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<internal::MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpStreamWriter:
MinidumpStreamType StreamType() const override;
private:
MINIDUMP_MEMORY_INFO_LIST memory_info_list_base_;
std::vector<MINIDUMP_MEMORY_INFO> items_;
DISALLOW_COPY_AND_ASSIGN(MinidumpMemoryInfoListWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_MEMORY_INFO_WRITER_H_
@@ -0,0 +1,172 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_MEMORY_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_MEMORY_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include <stdint.h>
#include <sys/types.h>
#include <memory>
#include <vector>
#include "base/macros.h"
#include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_writable.h"
#include "snapshot/memory_snapshot.h"
#include "util/file/file_io.h"
namespace crashpad {
//! \brief The base class for writers of memory ranges pointed to by
//! MINIDUMP_MEMORY_DESCRIPTOR objects in a minidump file.
class SnapshotMinidumpMemoryWriter : public internal::MinidumpWritable,
public MemorySnapshot::Delegate {
public:
explicit SnapshotMinidumpMemoryWriter(const MemorySnapshot* memory_snapshot);
~SnapshotMinidumpMemoryWriter() override;
//! \brief Returns a MINIDUMP_MEMORY_DESCRIPTOR referencing the data that this
//! object writes.
//!
//! This method is expected to be called by a MinidumpMemoryListWriter in
//! order to obtain a MINIDUMP_MEMORY_DESCRIPTOR to include in its list.
//!
//! \note Valid in #kStateWritable.
const MINIDUMP_MEMORY_DESCRIPTOR* MinidumpMemoryDescriptor() const;
//! \brief Registers a memory descriptor as one that should point to the
//! object on which this method is called.
//!
//! This method is expected to be called by objects of other classes, when
//! those other classes have their own memory descriptors that need to point
//! to memory ranges within a minidump file. MinidumpThreadWriter is one such
//! class. This method is public for this reason, otherwise it would suffice
//! to be private.
//!
//! \note Valid in #kStateFrozen or any preceding state.
void RegisterMemoryDescriptor(MINIDUMP_MEMORY_DESCRIPTOR* memory_descriptor);
private:
// MemorySnapshot::Delegate:
bool MemorySnapshotDelegateRead(void* data, size_t size) override;
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() final;
bool WriteObject(FileWriterInterface* file_writer) override;
//! \brief Returns the objects desired byte-boundary alignment.
//!
//! Memory regions are aligned to a 16-byte boundary. The actual alignment
//! requirements of any data within the memory region are unknown, and may be
//! more or less strict than this depending on the platform.
//!
//! \return `16`.
//!
//! \note Valid in #kStateFrozen or any subsequent state.
size_t Alignment() override;
bool WillWriteAtOffsetImpl(FileOffset offset) override;
//! \brief Returns the objects desired write phase.
//!
//! Memory regions are written at the end of minidump files, because it is
//! expected that unlike most other data in a minidump file, the contents of
//! memory regions will be accessed sparsely.
//!
//! \return #kPhaseLate.
//!
//! \note Valid in any state.
Phase WritePhase() final;
//! \brief Gets the underlying memory snapshot that the memory writer will
//! write to the minidump.
const MemorySnapshot& UnderlyingSnapshot() const { return *memory_snapshot_; }
MINIDUMP_MEMORY_DESCRIPTOR memory_descriptor_;
// weak
std::vector<MINIDUMP_MEMORY_DESCRIPTOR*> registered_memory_descriptors_;
const MemorySnapshot* memory_snapshot_;
FileWriterInterface* file_writer_;
DISALLOW_COPY_AND_ASSIGN(SnapshotMinidumpMemoryWriter);
};
//! \brief The writer for a MINIDUMP_MEMORY_LIST stream in a minidump file,
//! containing a list of MINIDUMP_MEMORY_DESCRIPTOR objects.
class MinidumpMemoryListWriter final : public internal::MinidumpStreamWriter {
public:
MinidumpMemoryListWriter();
~MinidumpMemoryListWriter() override;
//! \brief Adds a concrete initialized SnapshotMinidumpMemoryWriter for each
//! memory snapshot in \a memory_snapshots to the MINIDUMP_MEMORY_LIST.
//!
//! Memory snapshots are added in the fashion of AddMemory().
//!
//! \param[in] memory_snapshots The memory snapshots to use as source data.
//!
//! \note Valid in #kStateMutable.
void AddFromSnapshot(
const std::vector<const MemorySnapshot*>& memory_snapshots);
//! \brief Adds a SnapshotMinidumpMemoryWriter to the MINIDUMP_MEMORY_LIST.
//!
//! This object takes ownership of \a memory_writer and becomes its parent in
//! the overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void AddMemory(std::unique_ptr<SnapshotMinidumpMemoryWriter> memory_writer);
//! \brief Adds a SnapshotMinidumpMemoryWriter thats a child of another
//! internal::MinidumpWritable object to the MINIDUMP_MEMORY_LIST.
//!
//! \a memory_writer does not become a child of this object, but the
//! MINIDUMP_MEMORY_LIST will still contain a MINIDUMP_MEMORY_DESCRIPTOR for
//! it. \a memory_writer must be a child of another object in the
//! internal::MinidumpWritable tree.
//!
//! This method exists to be called by objects that have their own
//! SnapshotMinidumpMemoryWriter children but wish for them to also appear in
//! the minidump files MINIDUMP_MEMORY_LIST. MinidumpThreadWriter, which has
//! a SnapshotMinidumpMemoryWriter for thread stack memory, is an example.
//!
//! \note Valid in #kStateMutable.
void AddExtraMemory(SnapshotMinidumpMemoryWriter* memory_writer);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpStreamWriter:
MinidumpStreamType StreamType() const override;
private:
std::vector<SnapshotMinidumpMemoryWriter*> memory_writers_; // weak
std::vector<std::unique_ptr<SnapshotMinidumpMemoryWriter>> children_;
MINIDUMP_MEMORY_LIST memory_list_base_;
DISALLOW_COPY_AND_ASSIGN(MinidumpMemoryListWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_MEMORY_WRITER_H_
@@ -0,0 +1,142 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_MISC_INFO_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_MISC_INFO_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include <stdint.h>
#include <sys/types.h>
#include <time.h>
#include <string>
#include "base/macros.h"
#include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_writable.h"
namespace crashpad {
class ProcessSnapshot;
namespace internal {
//! \brief Returns the string to set in MINIDUMP_MISC_INFO_4::DbgBldStr.
//!
//! dbghelp produces strings like `"dbghelp.i386,6.3.9600.16520"` and
//! `"dbghelp.amd64,6.3.9600.16520"`. This function mimics that format, and adds
//! the OS that wrote the minidump along with any relevant platform-specific
//! data describing the compilation environment.
//!
//! This function is an implementation detail of
//! MinidumpMiscInfoWriter::InitializeFromSnapshot() and is only exposed for
//! testing purposes.
std::string MinidumpMiscInfoDebugBuildString();
} // namespace internal
//! \brief The writer for a stream in the MINIDUMP_MISC_INFO family in a
//! minidump file.
//!
//! The actual stream written will be a MINIDUMP_MISC_INFO,
//! MINIDUMP_MISC_INFO_2, MINIDUMP_MISC_INFO_3, MINIDUMP_MISC_INFO_4, or
//! MINIDUMP_MISC_INFO_5 stream. Later versions of MINIDUMP_MISC_INFO are
//! supersets of earlier versions. The earliest version that supports all of the
//! information that an object of this class contains will be used.
class MinidumpMiscInfoWriter final : public internal::MinidumpStreamWriter {
public:
MinidumpMiscInfoWriter();
~MinidumpMiscInfoWriter() override;
//! \brief Initializes MINIDUMP_MISC_INFO_N based on \a process_snapshot.
//!
//! \param[in] process_snapshot The process snapshot to use as source data.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromSnapshot(const ProcessSnapshot* process_snapshot);
//! \brief Sets the field referenced by #MINIDUMP_MISC1_PROCESS_ID.
void SetProcessID(uint32_t process_id);
//! \brief Sets the fields referenced by #MINIDUMP_MISC1_PROCESS_TIMES.
void SetProcessTimes(time_t process_create_time,
uint32_t process_user_time,
uint32_t process_kernel_time);
//! \brief Sets the fields referenced by #MINIDUMP_MISC1_PROCESSOR_POWER_INFO.
void SetProcessorPowerInfo(uint32_t processor_max_mhz,
uint32_t processor_current_mhz,
uint32_t processor_mhz_limit,
uint32_t processor_max_idle_state,
uint32_t processor_current_idle_state);
//! \brief Sets the field referenced by #MINIDUMP_MISC3_PROCESS_INTEGRITY.
void SetProcessIntegrityLevel(uint32_t process_integrity_level);
//! \brief Sets the field referenced by #MINIDUMP_MISC3_PROCESS_EXECUTE_FLAGS.
void SetProcessExecuteFlags(uint32_t process_execute_flags);
//! \brief Sets the field referenced by #MINIDUMP_MISC3_PROTECTED_PROCESS.
void SetProtectedProcess(uint32_t protected_process);
//! \brief Sets the fields referenced by #MINIDUMP_MISC3_TIMEZONE.
void SetTimeZone(uint32_t time_zone_id,
int32_t bias,
const std::string& standard_name,
const SYSTEMTIME& standard_date,
int32_t standard_bias,
const std::string& daylight_name,
const SYSTEMTIME& daylight_date,
int32_t daylight_bias);
//! \brief Sets the fields referenced by #MINIDUMP_MISC4_BUILDSTRING.
void SetBuildString(const std::string& build_string,
const std::string& debug_build_string);
// TODO(mark): Provide a better interface than this. Dont force callers to
// build their own XSTATE_CONFIG_FEATURE_MSC_INFO structure.
//
//! \brief Sets MINIDUMP_MISC_INFO_5::XStateData.
void SetXStateData(const XSTATE_CONFIG_FEATURE_MSC_INFO& xstate_data);
//! \brief Sets the field referenced by #MINIDUMP_MISC5_PROCESS_COOKIE.
void SetProcessCookie(uint32_t process_cookie);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
bool WriteObject(FileWriterInterface* file_writer) override;
MinidumpStreamType StreamType() const override;
private:
//! \brief Returns the size of the object to be written based on
//! MINIDUMP_MISC_INFO_N::Flags1.
//!
//! The smallest defined structure type in the MINIDUMP_MISC_INFO family that
//! can hold all of the data that has been populated will be used.
size_t CalculateSizeOfObjectFromFlags() const;
MINIDUMP_MISC_INFO_N misc_info_;
bool has_xstate_data_;
DISALLOW_COPY_AND_ASSIGN(MinidumpMiscInfoWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_MISC_INFO_WRITER_H_
@@ -0,0 +1,180 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_MODULE_CRASHPAD_INFO_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_MODULE_CRASHPAD_INFO_WRITER_H_
#include <stdint.h>
#include <sys/types.h>
#include <memory>
#include <vector>
#include "base/macros.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_string_writer.h"
#include "minidump/minidump_writable.h"
namespace crashpad {
class MinidumpAnnotationListWriter;
class MinidumpSimpleStringDictionaryWriter;
class ModuleSnapshot;
//! \brief The writer for a MinidumpModuleCrashpadInfo object in a minidump
//! file.
class MinidumpModuleCrashpadInfoWriter final
: public internal::MinidumpWritable {
public:
MinidumpModuleCrashpadInfoWriter();
~MinidumpModuleCrashpadInfoWriter() override;
//! \brief Initializes MinidumpModuleCrashpadInfo based on \a module_snapshot.
//!
//! Only data in \a module_snapshot that is considered useful will be
//! included. For simple annotations, usefulness is determined by
//! MinidumpSimpleStringDictionaryWriter::IsUseful().
//!
//! \param[in] module_snapshot The module snapshot to use as source data.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromSnapshot(const ModuleSnapshot* module_snapshot);
//! \brief Arranges for MinidumpModuleCrashpadInfo::list_annotations to point
//! to the internal::MinidumpUTF8StringListWriter object to be written by
//! \a list_annotations.
//!
//! This object takes ownership of \a simple_annotations and becomes its
//! parent in the overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void SetListAnnotations(
std::unique_ptr<MinidumpUTF8StringListWriter> list_annotations);
//! \brief Arranges for MinidumpModuleCrashpadInfo::simple_annotations to
//! point to the MinidumpSimpleStringDictionaryWriter object to be written
//! by \a simple_annotations.
//!
//! This object takes ownership of \a simple_annotations and becomes its
//! parent in the overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void SetSimpleAnnotations(
std::unique_ptr<MinidumpSimpleStringDictionaryWriter> simple_annotations);
//! \brief Arranges for MinidumpModuleCrashpadInfo::annotation_objects to
//! point to the MinidumpAnnotationListWriter object to be written by
//! \a annotation_objects.
//!
//! This object takes ownership of \a annotation_objects and becomes its
//! parent in the overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void SetAnnotationObjects(
std::unique_ptr<MinidumpAnnotationListWriter> annotation_objects);
//! \brief Determines whether the object is useful.
//!
//! A useful object is one that carries data that makes a meaningful
//! contribution to a minidump file. An object carrying list annotations or
//! simple annotations would be considered useful.
//!
//! \return `true` if the object is useful, `false` otherwise.
bool IsUseful() const;
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
MinidumpModuleCrashpadInfo module_;
std::unique_ptr<MinidumpUTF8StringListWriter> list_annotations_;
std::unique_ptr<MinidumpSimpleStringDictionaryWriter> simple_annotations_;
std::unique_ptr<MinidumpAnnotationListWriter> annotation_objects_;
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleCrashpadInfoWriter);
};
//! \brief The writer for a MinidumpModuleCrashpadInfoList object in a minidump
//! file, containing a list of MinidumpModuleCrashpadInfo objects.
class MinidumpModuleCrashpadInfoListWriter final
: public internal::MinidumpWritable {
public:
MinidumpModuleCrashpadInfoListWriter();
~MinidumpModuleCrashpadInfoListWriter() override;
//! \brief Adds an initialized MinidumpModuleCrashpadInfo for modules in \a
//! module_snapshots to the MinidumpModuleCrashpadInfoList.
//!
//! Only modules in \a module_snapshots that would produce a useful
//! MinidumpModuleCrashpadInfo structure are included. Usefulness is
//! determined by MinidumpModuleCrashpadInfoWriter::IsUseful().
//!
//! \param[in] module_snapshots The module snapshots to use as source data.
//!
//! \note Valid in #kStateMutable. AddModule() may not be called before this
//! method, and it is not normally necessary to call AddModule() after
//! this method.
void InitializeFromSnapshot(
const std::vector<const ModuleSnapshot*>& module_snapshots);
//! \brief Adds a MinidumpModuleCrashpadInfo to the
//! MinidumpModuleCrashpadInfoList.
//!
//! \param[in] module_crashpad_info Extended Crashpad-specific information
//! about the module. This object takes ownership of \a
//! module_crashpad_info and becomes its parent in the overall tree of
//! internal::MinidumpWritable objects.
//! \param[in] minidump_module_list_index The index of the MINIDUMP_MODULE in
//! the minidump files MINIDUMP_MODULE_LIST stream that corresponds to \a
//! module_crashpad_info.
//!
//! \note Valid in #kStateMutable.
void AddModule(
std::unique_ptr<MinidumpModuleCrashpadInfoWriter> module_crashpad_info,
size_t minidump_module_list_index);
//! \brief Determines whether the object is useful.
//!
//! A useful object is one that carries data that makes a meaningful
//! contribution to a minidump file. An object carrying children would be
//! considered useful.
//!
//! \return `true` if the object is useful, `false` otherwise.
bool IsUseful() const;
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
std::vector<std::unique_ptr<MinidumpModuleCrashpadInfoWriter>>
module_crashpad_infos_;
std::vector<MinidumpModuleCrashpadInfoLink> module_crashpad_info_links_;
MinidumpModuleCrashpadInfoList module_crashpad_info_list_base_;
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleCrashpadInfoListWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_MODULE_CRASHPAD_INFO_WRITER_H_
@@ -0,0 +1,352 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_MODULE_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_MODULE_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include <stdint.h>
#include <sys/types.h>
#include <time.h>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/strings/string16.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_writable.h"
namespace crashpad {
class ModuleSnapshot;
namespace internal {
class MinidumpUTF16StringWriter;
} // namespace internal
//! \brief The base class for writers of CodeView records referenced by
//! MINIDUMP_MODULE::CvRecord in minidump files.
class MinidumpModuleCodeViewRecordWriter : public internal::MinidumpWritable {
public:
~MinidumpModuleCodeViewRecordWriter() override;
protected:
MinidumpModuleCodeViewRecordWriter() : MinidumpWritable() {}
private:
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleCodeViewRecordWriter);
};
namespace internal {
//! \brief The base class for writers of CodeView records that serve as links to
//! `.pdb` (program database) files.
template <typename CodeViewRecordType>
class MinidumpModuleCodeViewRecordPDBLinkWriter
: public MinidumpModuleCodeViewRecordWriter {
public:
//! \brief Sets the name of the `.pdb` file being linked to.
void SetPDBName(const std::string& pdb_name) { pdb_name_ = pdb_name; }
protected:
MinidumpModuleCodeViewRecordPDBLinkWriter();
~MinidumpModuleCodeViewRecordPDBLinkWriter() override;
// MinidumpWritable:
size_t SizeOfObject() override;
bool WriteObject(FileWriterInterface* file_writer) override;
//! \brief Returns a pointer to the raw CodeView records data.
//!
//! Subclasses can use this to set fields in their codeview records other than
//! the `pdb_name` field.
CodeViewRecordType* codeview_record() { return &codeview_record_; }
private:
CodeViewRecordType codeview_record_;
std::string pdb_name_;
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleCodeViewRecordPDBLinkWriter);
};
} // namespace internal
//! \brief The writer for a CodeViewRecordPDB20 object in a minidump file.
//!
//! Most users will want MinidumpModuleCodeViewRecordPDB70Writer instead.
class MinidumpModuleCodeViewRecordPDB20Writer final
: public internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
CodeViewRecordPDB20> {
public:
MinidumpModuleCodeViewRecordPDB20Writer()
: internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
CodeViewRecordPDB20>() {}
~MinidumpModuleCodeViewRecordPDB20Writer() override;
//! \brief Sets CodeViewRecordPDB20::timestamp and CodeViewRecordPDB20::age.
void SetTimestampAndAge(time_t timestamp, uint32_t age);
private:
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleCodeViewRecordPDB20Writer);
};
//! \brief The writer for a CodeViewRecordPDB70 object in a minidump file.
class MinidumpModuleCodeViewRecordPDB70Writer final
: public internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
CodeViewRecordPDB70> {
public:
MinidumpModuleCodeViewRecordPDB70Writer()
: internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
CodeViewRecordPDB70>() {}
~MinidumpModuleCodeViewRecordPDB70Writer() override;
//! \brief Initializes the CodeViewRecordPDB70 based on \a module_snapshot.
//!
//! \param[in] module_snapshot The module snapshot to use as source data.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromSnapshot(const ModuleSnapshot* module_snapshot);
//! \brief Sets CodeViewRecordPDB70::uuid and CodeViewRecordPDB70::age.
void SetUUIDAndAge(const UUID& uuid, uint32_t age) {
codeview_record()->uuid = uuid;
codeview_record()->age = age;
}
private:
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleCodeViewRecordPDB70Writer);
};
//! \brief The writer for an IMAGE_DEBUG_MISC object in a minidump file.
//!
//! Most users will want MinidumpModuleCodeViewRecordPDB70Writer instead.
class MinidumpModuleMiscDebugRecordWriter final
: public internal::MinidumpWritable {
public:
MinidumpModuleMiscDebugRecordWriter();
~MinidumpModuleMiscDebugRecordWriter() override;
//! \brief Sets IMAGE_DEBUG_MISC::DataType.
void SetDataType(uint32_t data_type) {
image_debug_misc_.DataType = data_type;
}
//! \brief Sets IMAGE_DEBUG_MISC::Data, IMAGE_DEBUG_MISC::Length, and
//! IMAGE_DEBUG_MISC::Unicode.
//!
//! If \a utf16 is `true`, \a data will be treated as UTF-8 data and will be
//! converted to UTF-16, and IMAGE_DEBUG_MISC::Unicode will be set to `1`.
//! Otherwise, \a data will be used as-is and IMAGE_DEBUG_MISC::Unicode will
//! be set to `0`.
void SetData(const std::string& data, bool utf16);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
IMAGE_DEBUG_MISC image_debug_misc_;
std::string data_;
base::string16 data_utf16_;
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleMiscDebugRecordWriter);
};
//! \brief The writer for a MINIDUMP_MODULE object in a minidump file.
//!
//! Because MINIDUMP_MODULE objects only appear as elements of
//! MINIDUMP_MODULE_LIST objects, this class does not write any data on its own.
//! It makes its MINIDUMP_MODULE data available to its MinidumpModuleListWriter
//! parent, which writes it as part of a MINIDUMP_MODULE_LIST.
class MinidumpModuleWriter final : public internal::MinidumpWritable {
public:
MinidumpModuleWriter();
~MinidumpModuleWriter() override;
//! \brief Initializes the MINIDUMP_MODULE based on \a module_snapshot.
//!
//! \param[in] module_snapshot The module snapshot to use as source data.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromSnapshot(const ModuleSnapshot* module_snapshot);
//! \brief Returns a MINIDUMP_MODULE referencing this objects data.
//!
//! This method is expected to be called by a MinidumpModuleListWriter in
//! order to obtain a MINIDUMP_MODULE to include in its list.
//!
//! \note Valid in #kStateWritable.
const MINIDUMP_MODULE* MinidumpModule() const;
//! \brief Arranges for MINIDUMP_MODULE::ModuleNameRva to point to a
//! MINIDUMP_STRING containing \a name.
//!
//! A name is required in all MINIDUMP_MODULE objects.
//!
//! \note Valid in #kStateMutable.
void SetName(const std::string& name);
//! \brief Arranges for MINIDUMP_MODULE::CvRecord to point to a CodeView
//! record to be written by \a codeview_record.
//!
//! This object takes ownership of \a codeview_record and becomes its parent
//! in the overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void SetCodeViewRecord(
std::unique_ptr<MinidumpModuleCodeViewRecordWriter> codeview_record);
//! \brief Arranges for MINIDUMP_MODULE::MiscRecord to point to an
//! IMAGE_DEBUG_MISC object to be written by \a misc_debug_record.
//!
//! This object takes ownership of \a misc_debug_record and becomes its parent
//! in the overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void SetMiscDebugRecord(
std::unique_ptr<MinidumpModuleMiscDebugRecordWriter> misc_debug_record);
//! \brief Sets IMAGE_DEBUG_MISC::BaseOfImage.
void SetImageBaseAddress(uint64_t image_base_address) {
module_.BaseOfImage = image_base_address;
}
//! \brief Sets IMAGE_DEBUG_MISC::SizeOfImage.
void SetImageSize(uint32_t image_size) { module_.SizeOfImage = image_size; }
//! \brief Sets IMAGE_DEBUG_MISC::CheckSum.
void SetChecksum(uint32_t checksum) { module_.CheckSum = checksum; }
//! \brief Sets IMAGE_DEBUG_MISC::TimeDateStamp.
//!
//! \note Valid in #kStateMutable.
void SetTimestamp(time_t timestamp);
//! \brief Sets \ref VS_FIXEDFILEINFO::dwFileVersionMS
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileVersionMS" and \ref
//! VS_FIXEDFILEINFO::dwFileVersionLS
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileVersionLS".
//!
//! \note Valid in #kStateMutable.
void SetFileVersion(uint16_t version_0,
uint16_t version_1,
uint16_t version_2,
uint16_t version_3);
//! \brief Sets \ref VS_FIXEDFILEINFO::dwProductVersionMS
//! "IMAGE_DEBUG_MISC::VersionInfo::dwProductVersionMS" and \ref
//! VS_FIXEDFILEINFO::dwProductVersionLS
//! "IMAGE_DEBUG_MISC::VersionInfo::dwProductVersionLS".
//!
//! \note Valid in #kStateMutable.
void SetProductVersion(uint16_t version_0,
uint16_t version_1,
uint16_t version_2,
uint16_t version_3);
//! \brief Sets \ref VS_FIXEDFILEINFO::dwFileFlags
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileFlags" and \ref
//! VS_FIXEDFILEINFO::dwFileFlagsMask
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileFlagsMask".
//!
//! \note Valid in #kStateMutable.
void SetFileFlagsAndMask(uint32_t file_flags, uint32_t file_flags_mask);
//! \brief Sets \ref VS_FIXEDFILEINFO::dwFileOS
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileOS".
void SetFileOS(uint32_t file_os) { module_.VersionInfo.dwFileOS = file_os; }
//! \brief Sets \ref VS_FIXEDFILEINFO::dwFileType
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileType" and \ref
//! VS_FIXEDFILEINFO::dwFileSubtype
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileSubtype".
void SetFileTypeAndSubtype(uint32_t file_type, uint32_t file_subtype) {
module_.VersionInfo.dwFileType = file_type;
module_.VersionInfo.dwFileSubtype = file_subtype;
}
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
MINIDUMP_MODULE module_;
std::unique_ptr<internal::MinidumpUTF16StringWriter> name_;
std::unique_ptr<MinidumpModuleCodeViewRecordWriter> codeview_record_;
std::unique_ptr<MinidumpModuleMiscDebugRecordWriter> misc_debug_record_;
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleWriter);
};
//! \brief The writer for a MINIDUMP_MODULE_LIST stream in a minidump file,
//! containing a list of MINIDUMP_MODULE objects.
class MinidumpModuleListWriter final : public internal::MinidumpStreamWriter {
public:
MinidumpModuleListWriter();
~MinidumpModuleListWriter() override;
//! \brief Adds an initialized MINIDUMP_MODULE for each module in \a
//! module_snapshots to the MINIDUMP_MODULE_LIST.
//!
//! \param[in] module_snapshots The module snapshots to use as source data.
//!
//! \note Valid in #kStateMutable. AddModule() may not be called before this
//! method, and it is not normally necessary to call AddModule() after
//! this method.
void InitializeFromSnapshot(
const std::vector<const ModuleSnapshot*>& module_snapshots);
//! \brief Adds a MinidumpModuleWriter to the MINIDUMP_MODULE_LIST.
//!
//! This object takes ownership of \a module and becomes its parent in the
//! overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void AddModule(std::unique_ptr<MinidumpModuleWriter> module);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpStreamWriter:
MinidumpStreamType StreamType() const override;
private:
std::vector<std::unique_ptr<MinidumpModuleWriter>> modules_;
MINIDUMP_MODULE_LIST module_list_base_;
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleListWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_MODULE_WRITER_H_
@@ -0,0 +1,78 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_RVA_LIST_WRITER_H_
#define CRASHPAD_MINIDUMP_RVA_LIST_WRITER_H_
#include <stdint.h>
#include <sys/types.h>
#include <memory>
#include <vector>
#include "base/macros.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_writable.h"
namespace crashpad {
namespace internal {
//! \brief The writer for a MinidumpRVAList object in a minidump file,
//! containing a list of ::RVA pointers.
class MinidumpRVAListWriter : public MinidumpWritable {
protected:
MinidumpRVAListWriter();
~MinidumpRVAListWriter() override;
//! \brief Adds an ::RVA referencing an MinidumpWritable to the
//! MinidumpRVAList.
//!
//! This object takes ownership of \a child and becomes its parent in the
//! overall tree of MinidumpWritable objects.
//!
//! To provide type-correctness, subclasses are expected to provide a public
//! method that accepts a `scoped_ptr`-wrapped argument of the proper
//! MinidumpWritable subclass, and call this method with that argument.
//!
//! \note Valid in #kStateMutable.
void AddChild(std::unique_ptr<MinidumpWritable> child);
//! \brief Returns `true` if no child objects have been added by AddChild(),
//! and `false` if child objects are present.
bool IsEmpty() const { return children_.empty(); }
//! \brief Returns an objects ::RVA objects referencing its children.
//!
//! \note The returned vector will be empty until the object advances to
//! #kStateFrozen or beyond.
const std::vector<RVA>& child_rvas() const { return child_rvas_; }
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
std::unique_ptr<MinidumpRVAList> rva_list_base_;
std::vector<std::unique_ptr<MinidumpWritable>> children_;
std::vector<RVA> child_rvas_;
DISALLOW_COPY_AND_ASSIGN(MinidumpRVAListWriter);
};
} // namespace internal
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_RVA_LIST_WRITER_H_
@@ -0,0 +1,147 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_SIMPLE_STRING_DICTIONARY_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_SIMPLE_STRING_DICTIONARY_WRITER_H_
#include <sys/types.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_string_writer.h"
#include "minidump/minidump_writable.h"
namespace crashpad {
//! \brief The writer for a MinidumpSimpleStringDictionaryEntry object in a
//! minidump file.
//!
//! Because MinidumpSimpleStringDictionaryEntry objects only appear as elements
//! of MinidumpSimpleStringDictionary objects, this class does not write any
//! data on its own. It makes its MinidumpSimpleStringDictionaryEntry data
//! available to its MinidumpSimpleStringDictionaryWriter parent, which writes
//! it as part of a MinidumpSimpleStringDictionary.
class MinidumpSimpleStringDictionaryEntryWriter final
: public internal::MinidumpWritable {
public:
MinidumpSimpleStringDictionaryEntryWriter();
~MinidumpSimpleStringDictionaryEntryWriter() override;
//! \brief Returns a MinidumpSimpleStringDictionaryEntry referencing this
//! objects data.
//!
//! This method is expected to be called by a
//! MinidumpSimpleStringDictionaryWriter in order to obtain a
//! MinidumpSimpleStringDictionaryEntry to include in its list.
//!
//! \note Valid in #kStateWritable.
const MinidumpSimpleStringDictionaryEntry*
GetMinidumpSimpleStringDictionaryEntry() const;
//! \brief Sets the strings to be written as the entry objects key and value.
//!
//! \note Valid in #kStateMutable.
void SetKeyValue(const std::string& key, const std::string& value);
//! \brief Retrieves the key to be written.
//!
//! \note Valid in any state.
const std::string& Key() const { return key_.UTF8(); }
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
struct MinidumpSimpleStringDictionaryEntry entry_;
internal::MinidumpUTF8StringWriter key_;
internal::MinidumpUTF8StringWriter value_;
DISALLOW_COPY_AND_ASSIGN(MinidumpSimpleStringDictionaryEntryWriter);
};
//! \brief The writer for a MinidumpSimpleStringDictionary object in a minidump
//! file, containing a list of MinidumpSimpleStringDictionaryEntry objects.
//!
//! Because this class writes a representatin of a dictionary, the order of
//! entries is insignificant. Entries may be written in any order.
class MinidumpSimpleStringDictionaryWriter final
: public internal::MinidumpWritable {
public:
MinidumpSimpleStringDictionaryWriter();
~MinidumpSimpleStringDictionaryWriter() override;
//! \brief Adds an initialized MinidumpSimpleStringDictionaryEntryWriter for
//! each key-value pair in \a map to the MinidumpSimpleStringDictionary.
//!
//! \param[in] map The map to use as source data.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromMap(const std::map<std::string, std::string>& map);
//! \brief Adds a MinidumpSimpleStringDictionaryEntryWriter to the
//! MinidumpSimpleStringDictionary.
//!
//! This object takes ownership of \a entry and becomes its parent in the
//! overall tree of internal::MinidumpWritable objects.
//!
//! If the key contained in \a entry duplicates the key of an entry already
//! present in the MinidumpSimpleStringDictionary, the new \a entry will
//! replace the previous one.
//!
//! \note Valid in #kStateMutable.
void AddEntry(
std::unique_ptr<MinidumpSimpleStringDictionaryEntryWriter> entry);
//! \brief Determines whether the object is useful.
//!
//! A useful object is one that carries data that makes a meaningful
//! contribution to a minidump file. An object carrying entries would be
//! considered useful.
//!
//! \return `true` if the object is useful, `false` otherwise.
bool IsUseful() const;
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
// This object owns the MinidumpSimpleStringDictionaryEntryWriter objects.
std::map<std::string, MinidumpSimpleStringDictionaryEntryWriter*> entries_;
std::unique_ptr<MinidumpSimpleStringDictionary>
simple_string_dictionary_base_;
DISALLOW_COPY_AND_ASSIGN(MinidumpSimpleStringDictionaryWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_SIMPLE_STRING_DICTIONARY_WRITER_H_
@@ -0,0 +1,66 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_STREAM_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_STREAM_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include "base/macros.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_writable.h"
namespace crashpad {
namespace internal {
//! \brief The base class for all second-level objects (“streams”) in a minidump
//! file.
//!
//! Instances of subclasses of this class are children of the root-level
//! MinidumpFileWriter object.
class MinidumpStreamWriter : public MinidumpWritable {
public:
~MinidumpStreamWriter() override;
//! \brief Returns an objects stream type.
//!
//! \note Valid in any state.
virtual MinidumpStreamType StreamType() const = 0;
//! \brief Returns a MINIDUMP_DIRECTORY entry that serves as a pointer to this
//! stream.
//!
//! This method is provided for MinidumpFileWriter, which calls it in order to
//! obtain the directory entry for a stream.
//!
//! \note Valid only in #kStateWritable.
const MINIDUMP_DIRECTORY* DirectoryListEntry() const;
protected:
MinidumpStreamWriter();
// MinidumpWritable:
bool Freeze() override;
private:
MINIDUMP_DIRECTORY directory_list_entry_;
DISALLOW_COPY_AND_ASSIGN(MinidumpStreamWriter);
};
} // namespace internal
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_STREAM_WRITER_H_
@@ -0,0 +1,184 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_STRING_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_STRING_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include <sys/types.h>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/strings/string16.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_rva_list_writer.h"
#include "minidump/minidump_writable.h"
namespace crashpad {
namespace internal {
//! \cond
struct MinidumpStringWriterUTF16Traits {
using StringType = base::string16;
using MinidumpStringType = MINIDUMP_STRING;
};
struct MinidumpStringWriterUTF8Traits {
using StringType = std::string;
using MinidumpStringType = MinidumpUTF8String;
};
//! \endcond
//! \brief Writes a variable-length string to a minidump file in accordance with
//! the string types characteristics.
//!
//! MinidumpStringWriter objects should not be instantiated directly. To write
//! strings to minidump file, use the MinidumpUTF16StringWriter and
//! MinidumpUTF8StringWriter subclasses instead.
template <typename Traits>
class MinidumpStringWriter : public MinidumpWritable {
public:
MinidumpStringWriter();
~MinidumpStringWriter() override;
protected:
using MinidumpStringType = typename Traits::MinidumpStringType;
using StringType = typename Traits::StringType;
bool Freeze() override;
size_t SizeOfObject() override;
bool WriteObject(FileWriterInterface* file_writer) override;
//! \brief Sets the string to be written.
//!
//! \note Valid in #kStateMutable.
void set_string(const StringType& string) { string_.assign(string); }
//! \brief Retrieves the string to be written.
//!
//! \note Valid in any state.
const StringType& string() const { return string_; }
private:
std::unique_ptr<MinidumpStringType> string_base_;
StringType string_;
DISALLOW_COPY_AND_ASSIGN(MinidumpStringWriter);
};
//! \brief Writes a variable-length UTF-16-encoded MINIDUMP_STRING to a minidump
//! file.
//!
//! MinidumpUTF16StringWriter objects should not be instantiated directly
//! outside of the MinidumpWritable family of classes.
class MinidumpUTF16StringWriter final
: public MinidumpStringWriter<MinidumpStringWriterUTF16Traits> {
public:
MinidumpUTF16StringWriter() : MinidumpStringWriter() {}
~MinidumpUTF16StringWriter() override;
//! \brief Converts a UTF-8 string to UTF-16 and sets it as the string to be
//! written.
//!
//! \note Valid in #kStateMutable.
void SetUTF8(const std::string& string_utf8);
private:
DISALLOW_COPY_AND_ASSIGN(MinidumpUTF16StringWriter);
};
//! \brief Writes a variable-length UTF-8-encoded MinidumpUTF8String to a
//! minidump file.
//!
//! MinidumpUTF8StringWriter objects should not be instantiated directly outside
//! of the MinidumpWritable family of classes.
class MinidumpUTF8StringWriter final
: public MinidumpStringWriter<MinidumpStringWriterUTF8Traits> {
public:
MinidumpUTF8StringWriter() : MinidumpStringWriter() {}
~MinidumpUTF8StringWriter() override;
//! \brief Sets the string to be written.
//!
//! \note Valid in #kStateMutable.
void SetUTF8(const std::string& string_utf8) { set_string(string_utf8); }
//! \brief Retrieves the string to be written.
//!
//! \note Valid in any state.
const std::string& UTF8() const { return string(); }
private:
DISALLOW_COPY_AND_ASSIGN(MinidumpUTF8StringWriter);
};
//! \brief The writer for a MinidumpRVAList object in a minidump file,
//! containing a list of \a MinidumpStringWriterType objects.
template <typename MinidumpStringWriterType>
class MinidumpStringListWriter final : public MinidumpRVAListWriter {
public:
MinidumpStringListWriter();
~MinidumpStringListWriter() override;
//! \brief Adds a new \a Traits::MinidumpStringWriterType for each element in
//! \a vector to the MinidumpRVAList.
//!
//! \param[in] vector The vector to use as source data. Each string in the
//! vector is treated as a UTF-8 string, and a new string writer will be
//! created for each one and made a child of the MinidumpStringListWriter.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromVector(const std::vector<std::string>& vector);
//! \brief Creates a new \a Traits::MinidumpStringWriterType object and adds
//! it to the MinidumpRVAList.
//!
//! This object creates a new string writer with string value \a string_utf8,
//! takes ownership of it, and becomes its parent in the overall tree of
//! MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void AddStringUTF8(const std::string& string_utf8);
//! \brief Determines whether the object is useful.
//!
//! A useful object is one that carries data that makes a meaningful
//! contribution to a minidump file. An object carrying entries would be
//! considered useful.
//!
//! \return `true` if the object is useful, `false` otherwise.
bool IsUseful() const;
private:
DISALLOW_COPY_AND_ASSIGN(MinidumpStringListWriter);
};
} // namespace internal
using MinidumpUTF16StringListWriter = internal::MinidumpStringListWriter<
internal::MinidumpUTF16StringWriter>;
using MinidumpUTF8StringListWriter = internal::MinidumpStringListWriter<
internal::MinidumpUTF8StringWriter>;
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_STRING_WRITER_H_
@@ -0,0 +1,197 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_SYSTEM_INFO_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_SYSTEM_INFO_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include <stdint.h>
#include <sys/types.h>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_writable.h"
namespace crashpad {
class SystemSnapshot;
namespace internal {
class MinidumpUTF16StringWriter;
} // namespace internal
//! \brief The writer for a MINIDUMP_SYSTEM_INFO stream in a minidump file.
class MinidumpSystemInfoWriter final : public internal::MinidumpStreamWriter {
public:
MinidumpSystemInfoWriter();
~MinidumpSystemInfoWriter() override;
//! \brief Initializes MINIDUMP_SYSTEM_INFO based on \a system_snapshot.
//!
//! \param[in] system_snapshot The system snapshot to use as source data.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromSnapshot(const SystemSnapshot* system_snapshot);
//! \brief Sets MINIDUMP_SYSTEM_INFO::ProcessorArchitecture.
void SetCPUArchitecture(MinidumpCPUArchitecture processor_architecture) {
system_info_.ProcessorArchitecture = processor_architecture;
}
//! \brief Sets MINIDUMP_SYSTEM_INFO::ProcessorLevel and
//! MINIDUMP_SYSTEM_INFO::ProcessorRevision.
void SetCPULevelAndRevision(uint16_t processor_level,
uint16_t processor_revision) {
system_info_.ProcessorLevel = processor_level;
system_info_.ProcessorRevision = processor_revision;
}
//! \brief Sets MINIDUMP_SYSTEM_INFO::NumberOfProcessors.
void SetCPUCount(uint8_t number_of_processors) {
system_info_.NumberOfProcessors = number_of_processors;
}
//! \brief Sets MINIDUMP_SYSTEM_INFO::PlatformId.
void SetOS(MinidumpOS platform_id) { system_info_.PlatformId = platform_id; }
//! \brief Sets MINIDUMP_SYSTEM_INFO::ProductType.
void SetOSType(MinidumpOSType product_type) {
system_info_.ProductType = product_type;
}
//! \brief Sets MINIDUMP_SYSTEM_INFO::MajorVersion,
//! MINIDUMP_SYSTEM_INFO::MinorVersion, and
//! MINIDUMP_SYSTEM_INFO::BuildNumber.
void SetOSVersion(uint32_t major_version,
uint32_t minor_version,
uint32_t build_number) {
system_info_.MajorVersion = major_version;
system_info_.MinorVersion = minor_version;
system_info_.BuildNumber = build_number;
}
//! \brief Arranges for MINIDUMP_SYSTEM_INFO::CSDVersionRva to point to a
//! MINIDUMP_STRING containing the supplied string.
//!
//! This method must be called prior to Freeze(). A CSD version is required
//! in all MINIDUMP_SYSTEM_INFO streams. An empty string is an acceptable
//! value.
void SetCSDVersion(const std::string& csd_version);
//! \brief Sets MINIDUMP_SYSTEM_INFO::SuiteMask.
void SetSuiteMask(uint16_t suite_mask) {
system_info_.SuiteMask = suite_mask;
}
//! \brief Sets \ref CPU_INFORMATION::VendorId
//! "MINIDUMP_SYSTEM_INFO::Cpu::X86CpuInfo::VendorId".
//!
//! This is only valid if SetCPUArchitecture() has been used to set the CPU
//! architecture to #kMinidumpCPUArchitectureX86 or
//! #kMinidumpCPUArchitectureX86Win64.
//!
//! \param[in] ebx The first 4 bytes of the CPU vendor string, the value
//! reported in `cpuid 0` `ebx`.
//! \param[in] edx The middle 4 bytes of the CPU vendor string, the value
//! reported in `cpuid 0` `edx`.
//! \param[in] ecx The last 4 bytes of the CPU vendor string, the value
//! reported by `cpuid 0` `ecx`.
//!
//! \note Do not call this method if SetCPUArchitecture() has been used to set
//! the CPU architecture to #kMinidumpCPUArchitectureAMD64.
//!
//! \sa SetCPUX86VendorString()
void SetCPUX86Vendor(uint32_t ebx, uint32_t edx, uint32_t ecx);
//! \brief Sets \ref CPU_INFORMATION::VendorId
//! "MINIDUMP_SYSTEM_INFO::Cpu::X86CpuInfo::VendorId".
//!
//! This is only valid if SetCPUArchitecture() has been used to set the CPU
//! architecture to #kMinidumpCPUArchitectureX86 or
//! #kMinidumpCPUArchitectureX86Win64.
//!
//! \param[in] vendor The entire CPU vendor string, which must be exactly 12
//! bytes long.
//!
//! \note Do not call this method if SetCPUArchitecture() has been used to set
//! the CPU architecture to #kMinidumpCPUArchitectureAMD64.
//!
//! \sa SetCPUX86Vendor()
void SetCPUX86VendorString(const std::string& vendor);
//! \brief Sets \ref CPU_INFORMATION::VersionInformation
//! "MINIDUMP_SYSTEM_INFO::Cpu::X86CpuInfo::VersionInformation" and
//! \ref CPU_INFORMATION::FeatureInformation
//! "MINIDUMP_SYSTEM_INFO::Cpu::X86CpuInfo::FeatureInformation".
//!
//! This is only valid if SetCPUArchitecture() has been used to set the CPU
//! architecture to #kMinidumpCPUArchitectureX86 or
//! #kMinidumpCPUArchitectureX86Win64.
//!
//! \note Do not call this method if SetCPUArchitecture() has been used to set
//! the CPU architecture to #kMinidumpCPUArchitectureAMD64.
void SetCPUX86VersionAndFeatures(uint32_t version, uint32_t features);
//! \brief Sets \ref CPU_INFORMATION::AMDExtendedCpuFeatures
//! "MINIDUMP_SYSTEM_INFO::Cpu::X86CpuInfo::AMDExtendedCPUFeatures".
//!
//! This is only valid if SetCPUArchitecture() has been used to set the CPU
//! architecture to #kMinidumpCPUArchitectureX86 or
//! #kMinidumpCPUArchitectureX86Win64, and if SetCPUX86Vendor() or
//! SetCPUX86VendorString() has been used to set the CPU vendor to
//! “AuthenticAMD”.
//!
//! \note Do not call this method if SetCPUArchitecture() has been used to set
//! the CPU architecture to #kMinidumpCPUArchitectureAMD64.
void SetCPUX86AMDExtendedFeatures(uint32_t extended_features);
//! \brief Sets \ref CPU_INFORMATION::ProcessorFeatures
//! "MINIDUMP_SYSTEM_INFO::Cpu::OtherCpuInfo::ProcessorFeatures".
//!
//! This is only valid if SetCPUArchitecture() has been used to set the CPU
//! architecture to an architecture other than #kMinidumpCPUArchitectureX86
//! or #kMinidumpCPUArchitectureX86Win64.
//!
//! \note This method may be called if SetCPUArchitecture() has been used to
//! set the CPU architecture to #kMinidumpCPUArchitectureAMD64.
void SetCPUOtherFeatures(uint64_t features_0, uint64_t features_1);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpStreamWriter:
MinidumpStreamType StreamType() const override;
private:
MINIDUMP_SYSTEM_INFO system_info_;
std::unique_ptr<internal::MinidumpUTF16StringWriter> csd_version_;
DISALLOW_COPY_AND_ASSIGN(MinidumpSystemInfoWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_SYSTEM_INFO_WRITER_H_
@@ -0,0 +1,52 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_THREAD_ID_MAP_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_THREAD_ID_MAP_H_
#include <stdint.h>
#include <map>
#include <vector>
namespace crashpad {
class ThreadSnapshot;
//! \brief A map that connects 64-bit snapshot thread IDs to 32-bit minidump
//! thread IDs.
//!
//! 64-bit snapshot thread IDs are obtained from ThreadSnapshot::ThreadID().
//! 32-bit minidump thread IDs are stored in MINIDUMP_THREAD::ThreadId.
//!
//! A ThreadIDMap ensures that there are no collisions among the set of 32-bit
//! minidump thread IDs.
using MinidumpThreadIDMap = std::map<uint64_t, uint32_t>;
//! \brief Builds a MinidumpThreadIDMap for a group of ThreadSnapshot objects.
//!
//! \param[in] thread_snapshots The thread snapshots to use as source data.
//! \param[out] thread_id_map A MinidumpThreadIDMap to be built by this method.
//! This map must be empty when this function is called.
//!
//! The map ensures that for any unique 64-bit thread ID found in a
//! ThreadSnapshot, the 32-bit thread ID used in a minidump file will also be
//! unique.
void BuildMinidumpThreadIDMap(
const std::vector<const ThreadSnapshot*>& thread_snapshots,
MinidumpThreadIDMap* thread_id_map);
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_THREAD_ID_MAP_H_
@@ -0,0 +1,214 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_THREAD_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_THREAD_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include <stdint.h>
#include <sys/types.h>
#include <memory>
#include <vector>
#include "base/macros.h"
#include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_thread_id_map.h"
#include "minidump/minidump_writable.h"
namespace crashpad {
class MinidumpContextWriter;
class MinidumpMemoryListWriter;
class SnapshotMinidumpMemoryWriter;
class ThreadSnapshot;
//! \brief The writer for a MINIDUMP_THREAD object in a minidump file.
//!
//! Because MINIDUMP_THREAD objects only appear as elements of
//! MINIDUMP_THREAD_LIST objects, this class does not write any data on its own.
//! It makes its MINIDUMP_THREAD data available to its MinidumpThreadListWriter
//! parent, which writes it as part of a MINIDUMP_THREAD_LIST.
class MinidumpThreadWriter final : public internal::MinidumpWritable {
public:
MinidumpThreadWriter();
~MinidumpThreadWriter() override;
//! \brief Initializes the MINIDUMP_THREAD based on \a thread_snapshot.
//!
//! \param[in] thread_snapshot The thread snapshot to use as source data.
//! \param[in] thread_id_map A MinidumpThreadIDMap to be consulted to
//! determine the 32-bit minidump thread ID to use for \a thread_snapshot.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromSnapshot(const ThreadSnapshot* thread_snapshot,
const MinidumpThreadIDMap* thread_id_map);
//! \brief Returns a MINIDUMP_THREAD referencing this objects data.
//!
//! This method is expected to be called by a MinidumpThreadListWriter in
//! order to obtain a MINIDUMP_THREAD to include in its list.
//!
//! \note Valid in #kStateWritable.
const MINIDUMP_THREAD* MinidumpThread() const;
//! \brief Returns a SnapshotMinidumpMemoryWriter that will write the memory
//! region corresponding to this objects stack.
//!
//! If the thread does not have a stack, or its stack could not be determined,
//! this will return `nullptr`.
//!
//! This method is provided so that MinidumpThreadListWriter can obtain thread
//! stack memory regions for the purposes of adding them to a
//! MinidumpMemoryListWriter (configured by calling
//! MinidumpThreadListWriter::SetMemoryListWriter()) by calling
//! MinidumpMemoryListWriter::AddExtraMemory().
//!
//! \note Valid in any state.
SnapshotMinidumpMemoryWriter* Stack() const { return stack_.get(); }
//! \brief Arranges for MINIDUMP_THREAD::Stack to point to the MINIDUMP_MEMORY
//! object to be written by \a stack.
//!
//! This object takes ownership of \a stack and becomes its parent in the
//! overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void SetStack(std::unique_ptr<SnapshotMinidumpMemoryWriter> stack);
//! \brief Arranges for MINIDUMP_THREAD::ThreadContext to point to the CPU
//! context to be written by \a context.
//!
//! A context is required in all MINIDUMP_THREAD objects.
//!
//! This object takes ownership of \a context and becomes its parent in the
//! overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void SetContext(std::unique_ptr<MinidumpContextWriter> context);
//! \brief Sets MINIDUMP_THREAD::ThreadId.
void SetThreadID(uint32_t thread_id) { thread_.ThreadId = thread_id; }
//! \brief Sets MINIDUMP_THREAD::SuspendCount.
void SetSuspendCount(uint32_t suspend_count) {
thread_.SuspendCount = suspend_count;
}
//! \brief Sets MINIDUMP_THREAD::PriorityClass.
void SetPriorityClass(uint32_t priority_class) {
thread_.PriorityClass = priority_class;
}
//! \brief Sets MINIDUMP_THREAD::Priority.
void SetPriority(uint32_t priority) { thread_.Priority = priority; }
//! \brief Sets MINIDUMP_THREAD::Teb.
void SetTEB(uint64_t teb) { thread_.Teb = teb; }
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
MINIDUMP_THREAD thread_;
std::unique_ptr<SnapshotMinidumpMemoryWriter> stack_;
std::unique_ptr<MinidumpContextWriter> context_;
DISALLOW_COPY_AND_ASSIGN(MinidumpThreadWriter);
};
//! \brief The writer for a MINIDUMP_THREAD_LIST stream in a minidump file,
//! containing a list of MINIDUMP_THREAD objects.
class MinidumpThreadListWriter final : public internal::MinidumpStreamWriter {
public:
MinidumpThreadListWriter();
~MinidumpThreadListWriter() override;
//! \brief Adds an initialized MINIDUMP_THREAD for each thread in \a
//! thread_snapshots to the MINIDUMP_THREAD_LIST.
//!
//! \param[in] thread_snapshots The thread snapshots to use as source data.
//! \param[out] thread_id_map A MinidumpThreadIDMap to be built by this
//! method. This map must be empty when this method is called.
//!
//! \note Valid in #kStateMutable. AddThread() may not be called before this
//! method, and it is not normally necessary to call AddThread() after
//! this method.
void InitializeFromSnapshot(
const std::vector<const ThreadSnapshot*>& thread_snapshots,
MinidumpThreadIDMap* thread_id_map);
//! \brief Sets the MinidumpMemoryListWriter that each threads stack memory
//! region should be added to as extra memory.
//!
//! Each MINIDUMP_THREAD object can contain a reference to a
//! SnapshotMinidumpMemoryWriter object that contains a snapshot of its stac
//! memory. In the overall tree of internal::MinidumpWritable objects, these
//! SnapshotMinidumpMemoryWriter objects are considered children of their
//! MINIDUMP_THREAD, and are referenced by a MINIDUMP_MEMORY_DESCRIPTOR
//! contained in the MINIDUMP_THREAD. It is also possible for the same memory
//! regions to have MINIDUMP_MEMORY_DESCRIPTOR objects present in a
//! MINIDUMP_MEMORY_LIST stream. This is accomplished by calling this method,
//! which informs a MinidumpThreadListWriter that it should call
//! MinidumpMemoryListWriter::AddExtraMemory() for each extant thread stack
//! while the thread is being added in AddThread(). When this is done, the
//! MinidumpMemoryListWriter will contain a MINIDUMP_MEMORY_DESCRIPTOR
//! pointing to the threads stack memory in its MINIDUMP_MEMORY_LIST. Note
//! that the actual contents of the memory is only written once, as a child of
//! the MinidumpThreadWriter. The MINIDUMP_MEMORY_DESCRIPTOR objects in both
//! the MINIDUMP_THREAD and MINIDUMP_MEMORY_LIST will point to the same copy
//! of the memorys contents.
//!
//! \note This method must be called before AddThread() is called. Threads
//! added by AddThread() prior to this method being called will not have
//! their stacks added to \a memory_list_writer as extra memory.
//! \note Valid in #kStateMutable.
void SetMemoryListWriter(MinidumpMemoryListWriter* memory_list_writer);
//! \brief Adds a MinidumpThreadWriter to the MINIDUMP_THREAD_LIST.
//!
//! This object takes ownership of \a thread and becomes its parent in the
//! overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void AddThread(std::unique_ptr<MinidumpThreadWriter> thread);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpStreamWriter:
MinidumpStreamType StreamType() const override;
private:
std::vector<std::unique_ptr<MinidumpThreadWriter>> threads_;
MinidumpMemoryListWriter* memory_list_writer_; // weak
MINIDUMP_THREAD_LIST thread_list_base_;
DISALLOW_COPY_AND_ASSIGN(MinidumpThreadListWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_THREAD_WRITER_H_
@@ -0,0 +1,154 @@
// Copyright 2016 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_UNLOADED_MODULE_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_UNLOADED_MODULE_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include <stdint.h>
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_string_writer.h"
#include "minidump/minidump_writable.h"
#include "snapshot/unloaded_module_snapshot.h"
namespace crashpad {
//! \brief The writer for a MINIDUMP_UNLOADED_MODULE object in a minidump file.
//!
//! Because MINIDUMP_UNLOADED_MODULE objects only appear as elements of
//! MINIDUMP_UNLOADED_MODULE_LIST objects, this class does not write any data on
//! its own. It makes its MINIDUMP_UNLOADED_MODULE data available to its
//! MinidumpUnloadedModuleListWriter parent, which writes it as part of a
//! MINIDUMP_UNLOADED_MODULE_LIST.
class MinidumpUnloadedModuleWriter final : public internal::MinidumpWritable {
public:
MinidumpUnloadedModuleWriter();
~MinidumpUnloadedModuleWriter() override;
//! \brief Initializes the MINIDUMP_UNLOADED_MODULE based on \a
//! unloaded_module_snapshot.
//!
//! \param[in] unloaded_module_snapshot The unloaded module snapshot to use as
//! source data.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromSnapshot(
const UnloadedModuleSnapshot& unloaded_module_snapshot);
//! \brief Returns a MINIDUMP_UNLOADED_MODULE referencing this objects data.
//!
//! This method is expected to be called by a MinidumpUnloadedModuleListWriter
//! in order to obtain a MINIDUMP_UNLOADED_MODULE to include in its list.
//!
//! \note Valid in #kStateWritable.
const MINIDUMP_UNLOADED_MODULE* MinidumpUnloadedModule() const;
//! \brief Arranges for MINIDUMP_UNLOADED_MODULE::ModuleNameRva to point to a
//! MINIDUMP_STRING containing \a name.
//!
//! \note Valid in #kStateMutable.
void SetName(const std::string& name);
//! \brief Sets MINIDUMP_UNLOADED_MODULE::BaseOfImage.
void SetImageBaseAddress(uint64_t image_base_address) {
unloaded_module_.BaseOfImage = image_base_address;
}
//! \brief Sets MINIDUMP_UNLOADED_MODULE::SizeOfImage.
void SetImageSize(uint32_t image_size) {
unloaded_module_.SizeOfImage = image_size;
}
//! \brief Sets MINIDUMP_UNLOADED_MODULE::CheckSum.
void SetChecksum(uint32_t checksum) { unloaded_module_.CheckSum = checksum; }
//! \brief Sets MINIDUMP_UNLOADED_MODULE::TimeDateStamp.
//!
//! \note Valid in #kStateMutable.
void SetTimestamp(time_t timestamp);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
MINIDUMP_UNLOADED_MODULE unloaded_module_;
std::unique_ptr<internal::MinidumpUTF16StringWriter> name_;
DISALLOW_COPY_AND_ASSIGN(MinidumpUnloadedModuleWriter);
};
//! \brief The writer for a MINIDUMP_UNLOADED_MODULE_LIST stream in a minidump
//! file, containing a list of MINIDUMP_UNLOADED_MODULE objects.
class MinidumpUnloadedModuleListWriter final
: public internal::MinidumpStreamWriter {
public:
MinidumpUnloadedModuleListWriter();
~MinidumpUnloadedModuleListWriter() override;
//! \brief Adds an initialized MINIDUMP_UNLOADED_MODULE for each unloaded
//! module in \a unloaded_module_snapshots to the
//! MINIDUMP_UNLOADED_MODULE_LIST.
//!
//! \param[in] unloaded_module_snapshots The unloaded module snapshots to use
//! as source data.
//!
//! \note Valid in #kStateMutable. AddUnloadedModule() may not be called
//! before this this method, and it is not normally necessary to call
//! AddUnloadedModule() after this method.
void InitializeFromSnapshot(
const std::vector<UnloadedModuleSnapshot>& unloaded_module_snapshots);
//! \brief Adds a MinidumpUnloadedModuleWriter to the
//! MINIDUMP_UNLOADED_MODULE_LIST.
//!
//! This object takes ownership of \a unloaded_module and becomes its parent
//! in the overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void AddUnloadedModule(
std::unique_ptr<MinidumpUnloadedModuleWriter> unloaded_module);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpStreamWriter:
MinidumpStreamType StreamType() const override;
private:
std::vector<std::unique_ptr<MinidumpUnloadedModuleWriter>> unloaded_modules_;
MINIDUMP_UNLOADED_MODULE_LIST unloaded_module_list_base_;
DISALLOW_COPY_AND_ASSIGN(MinidumpUnloadedModuleListWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_UNLOADED_MODULE_WRITER_H_
@@ -0,0 +1,84 @@
// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_USER_EXTENSION_STREAM_DATA_SOURCE_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_USER_EXTENSION_STREAM_DATA_SOURCE_H_
#include <stdint.h>
#include <sys/types.h>
#include "base/macros.h"
#include "minidump/minidump_extensions.h"
namespace crashpad {
//! \brief Describes a user extension data stream in a minidump.
class MinidumpUserExtensionStreamDataSource {
public:
//! \brief An interface implemented by readers of
//! MinidumpUserExtensionStreamDataSource.
class Delegate {
public:
//! \brief Called by MinidumpUserExtensionStreamDataSource::Read() to
//! provide data requested by a call to that method.
//!
//! \param[in] data A pointer to the data that was read. The callee does not
//! take ownership of this data. This data is only valid for the
//! duration of the call to this method. This parameter may be `nullptr`
//! if \a size is `0`.
//! \param[in] size The size of the data that was read.
//!
//! \return `true` on success, `false` on failure.
//! MinidumpUserExtensionStreamDataSource::ReadStreamData() will use
//! this as its own return value.
virtual bool ExtensionStreamDataSourceRead(const void* data,
size_t size) = 0;
protected:
~Delegate() {}
};
//! \brief Constructs a MinidumpUserExtensionStreamDataSource.
//!
//! \param[in] stream_type The type of the user extension stream.
explicit MinidumpUserExtensionStreamDataSource(uint32_t stream_type);
virtual ~MinidumpUserExtensionStreamDataSource();
MinidumpStreamType stream_type() const { return stream_type_; }
//! \brief The size of this data stream.
virtual size_t StreamDataSize() = 0;
//! \brief Calls Delegate::UserStreamDataSourceRead(), providing it with
//! the stream data.
//!
//! Implementations do not necessarily compute the stream data prior to
//! this method being called. The stream data may be computed or loaded
//! lazily and may be discarded after being passed to the delegate.
//!
//! \return `false` on failure, otherwise, the return value of
//! Delegate::ExtensionStreamDataSourceRead(), which should be `true` on
//! success and `false` on failure.
virtual bool ReadStreamData(Delegate* delegate) = 0;
private:
MinidumpStreamType stream_type_;
DISALLOW_COPY_AND_ASSIGN(MinidumpUserExtensionStreamDataSource);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_USER_EXTENSION_STREAM_DATA_SOURCE_H_
@@ -0,0 +1,79 @@
// Copyright 2016 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_USER_STREAM_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_USER_STREAM_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/macros.h"
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_writable.h"
#include "minidump/minidump_user_extension_stream_data_source.h"
#include "snapshot/module_snapshot.h"
namespace crashpad {
//! \brief The writer for a MINIDUMP_USER_STREAM in a minidump file.
class MinidumpUserStreamWriter final : public internal::MinidumpStreamWriter {
public:
MinidumpUserStreamWriter();
~MinidumpUserStreamWriter() override;
//! \brief Initializes a MINIDUMP_USER_STREAM based on \a stream.
//!
//! \param[in] stream The memory and stream type to use as source data.
//!
//! \note Valid in #kStateMutable.
void InitializeFromSnapshot(const UserMinidumpStream* stream);
//! \brief Initializes a MINIDUMP_USER_STREAM based on \a data_source.
//!
//! \param[in] data_source The content and type of the stream.
//!
//! \note Valid in #kStateMutable.
void InitializeFromUserExtensionStream(
std::unique_ptr<MinidumpUserExtensionStreamDataSource> data_source);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<internal::MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpStreamWriter:
MinidumpStreamType StreamType() const override;
private:
class ContentsWriter;
class SnapshotContentsWriter;
class ExtensionStreamContentsWriter;
std::unique_ptr<ContentsWriter> contents_writer_;
MinidumpStreamType stream_type_;
DISALLOW_COPY_AND_ASSIGN(MinidumpUserStreamWriter);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_USER_STREAM_WRITER_H_
@@ -0,0 +1,280 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_WRITABLE_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_WRITABLE_H_
#include <windows.h>
#include <dbghelp.h>
#include <sys/types.h>
#include <limits>
#include <vector>
#include "base/macros.h"
#include "util/file/file_io.h"
namespace crashpad {
class FileWriterInterface;
namespace internal {
//! \brief The base class for all content that might be written to a minidump
//! file.
class MinidumpWritable {
public:
virtual ~MinidumpWritable();
//! \brief Writes an object and all of its children to a minidump file.
//!
//! Use this on the root object of a tree of MinidumpWritable objects,
//! typically on a MinidumpFileWriter object.
//!
//! \param[in] file_writer The file writer to receive the minidump files
//! content.
//!
//! \return `true` on success. `false` on failure, with an appropriate message
//! logged.
//!
//! \note Valid in #kStateMutable, and transitions the object and the entire
//! tree beneath it through all states to #kStateWritten.
//!
//! \note This method should rarely be overridden.
virtual bool WriteEverything(FileWriterInterface* file_writer);
//! \brief Registers a file offset pointer as one that should point to the
//! object on which this method is called.
//!
//! Once the file offset at which an object will be written is known (when it
//! enters #kStateWritable), registered RVA pointers will be updated.
//!
//! \param[in] rva A pointer to storage for the file offset that should
//! contain this objects writable file offset, once it is known.
//!
//! \note Valid in #kStateFrozen or any preceding state.
//
// This is public instead of protected because objects of derived classes need
// to be able to register their own pointers with distinct objects.
void RegisterRVA(RVA* rva);
//! \brief Registers a location descriptor as one that should point to the
//! object on which this method is called.
//!
//! Once an objects size and the file offset at it will be written is known
//! (when it enters #kStateFrozen), the relevant data in registered location
//! descriptors will be updated.
//!
//! \param[in] location_descriptor A pointer to a location descriptor that
//! should contain this objects writable size and file offset, once they
//! are known.
//!
//! \note Valid in #kStateFrozen or any preceding state.
//
// This is public instead of protected because objects of derived classes need
// to be able to register their own pointers with distinct objects.
void RegisterLocationDescriptor(
MINIDUMP_LOCATION_DESCRIPTOR* location_descriptor);
protected:
//! \brief Identifies the state of an object.
//!
//! Objects will normally transition through each of these states as they are
//! created, populated with data, and then written to a minidump file.
enum State {
//! \brief The objects properties can be modified.
kStateMutable = 0,
//! \brief The object is “frozen”.
//!
//! Its properties cannot be modified. Pointers to file offsets of other
//! structures may not yet be valid.
kStateFrozen,
//! \brief The object is writable.
//!
//! The file offset at which it will be written is known. Pointers to file
//! offsets of other structures are valid when all objects in a tree are in
//! this state.
kStateWritable,
//! \brief The object has been written to a minidump file.
kStateWritten,
};
//! \brief Identifies the phase during which an object will be written to a
//! minidump file.
enum Phase {
//! \brief Objects that are written to a minidump file “early”.
//!
//! The normal sequence is for an object to write itself and then write all
//! of its children.
kPhaseEarly = 0,
//! \brief Objects that are written to a minidump file “late”.
//!
//! Some objects, such as those capturing memory region snapshots, are
//! written to minidump files after all other objects. This “late” phase
//! identifies such objects. This is useful to improve spatial locality in
//! minidump files in accordance with expected access patterns: unlike most
//! other data, memory snapshots are large and do not usually need to be
//! consulted in their entirety in order to process a minidump file.
kPhaseLate,
};
//! \brief A size value used to signal failure by methods that return
//! `size_t`.
static constexpr size_t kInvalidSize = std::numeric_limits<size_t>::max();
MinidumpWritable();
//! \brief The state of the object.
State state() const { return state_; }
//! \brief Transitions the object from #kStateMutable to #kStateFrozen.
//!
//! The default implementation marks the object as frozen and recursively
//! calls Freeze() on all of its children. Subclasses may override this method
//! to perform processing that should only be done once callers have finished
//! populating an object with data. Typically, a subclass implementation would
//! call RegisterRVA() or RegisterLocationDescriptor() on other objects as
//! appropriate, because at the time Freeze() runs, the in-memory locations of
//! RVAs and location descriptors are known and will not change for the
//! remaining duration of an objects lifetime.
//!
//! \return `true` on success. `false` on failure, with an appropriate message
//! logged.
virtual bool Freeze();
//! \brief Returns the amount of space that this object will consume when
//! written to a minidump file, in bytes, not including any leading or
//! trailing padding necessary to maintain proper alignment.
//!
//! \note Valid in #kStateFrozen or any subsequent state.
virtual size_t SizeOfObject() = 0;
//! \brief Returns the objects desired byte-boundary alignment.
//!
//! The default implementation returns `4`. Subclasses may override this as
//! needed.
//!
//! \note Valid in #kStateFrozen or any subsequent state.
virtual size_t Alignment();
//! \brief Returns the objects children.
//!
//! \note Valid in #kStateFrozen or any subsequent state.
virtual std::vector<MinidumpWritable*> Children();
//! \brief Returns the objects desired write phase.
//!
//! The default implementation returns #kPhaseEarly. Subclasses may override
//! this method to alter their write phase.
//!
//! \note Valid in any state.
virtual Phase WritePhase();
//! \brief Prepares the object to be written at a known file offset,
//! transitioning it from #kStateFrozen to #kStateWritable.
//!
//! This method is responsible for determining the final file offset of the
//! object, which may be increased from \a offset to meet alignment
//! requirements. It calls WillWriteAtOffsetImpl() for the benefit of
//! subclasses. It populates all RVAs and location descriptors registered with
//! it via RegisterRVA() and RegisterLocationDescriptor(). It also recurses
//! into all known children.
//!
//! \param[in] phase The phase during which the object will be written. If
//! this does not match Phase(), processing is suppressed, although
//! recursive processing will still occur on all children. This addresses
//! the case where parents and children do not write in the same phase.
//! \param[in] offset The file offset at which the object will be written. The
//! offset may need to be adjusted for alignment.
//! \param[out] write_sequence This object will append itself to this list,
//! such that on return from a recursive tree of WillWriteAtOffset()
//! calls, elements of the vector will be organized in the sequence that
//! the objects will be written to the minidump file.
//!
//! \return The file size consumed by this object and all children, including
//! any padding inserted to meet alignment requirements. On failure,
//! #kInvalidSize, with an appropriate message logged.
//!
//! \note This method cannot be overridden. Subclasses that need to perform
//! processing when an object transitions to #kStateWritable should
//! implement WillWriteAtOffsetImpl(), which is called by this method.
size_t WillWriteAtOffset(Phase phase,
FileOffset* offset,
std::vector<MinidumpWritable*>* write_sequence);
//! \brief Called once an objects writable file offset is determined, as it
//! transitions into #kStateWritable.
//!
//! Subclasses can override this method if they need to provide additional
//! processing once their writable file offset is known. Typically, this will
//! be done by subclasses that handle certain RVAs themselves instead of using
//! the RegisterRVA() interface.
//!
//! \param[in] offset The file offset at which the object will be written. The
//! value passed to this method will already have been adjusted to meet
//! alignment requirements.
//!
//! \return `true` on success. `false` on error, indicating that the minidump
//! file should not be written.
//!
//! \note Valid in #kStateFrozen. The object will transition to
//! #kStateWritable after this method returns.
virtual bool WillWriteAtOffsetImpl(FileOffset offset);
//! \brief Writes the object, transitioning it from #kStateWritable to
//! #kStateWritten.
//!
//! Writes any padding necessary to meet alignment requirements, and then
//! calls WriteObject() to write the objects content.
//!
//! \param[in] file_writer The file writer to receive the objects content.
//!
//! \return `true` on success. `false` on error with an appropriate message
//! logged.
//!
//! \note This method cannot be overridden. Subclasses must override
//! WriteObject().
bool WritePaddingAndObject(FileWriterInterface* file_writer);
//! \brief Writes the objects content.
//!
//! \param[in] file_writer The file writer to receive the objects content.
//!
//! \return `true` on success. `false` on error, indicating that the content
//! could not be written to the minidump file.
//!
//! \note Valid in #kStateWritable. The object will transition to
//! #kStateWritten after this method returns.
virtual bool WriteObject(FileWriterInterface* file_writer) = 0;
private:
std::vector<RVA*> registered_rvas_; // weak
// weak
std::vector<MINIDUMP_LOCATION_DESCRIPTOR*> registered_location_descriptors_;
size_t leading_pad_bytes_;
State state_;
DISALLOW_COPY_AND_ASSIGN(MinidumpWritable);
};
} // namespace internal
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_WRITABLE_H_
@@ -0,0 +1,90 @@
// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_WRITER_UTIL_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_WRITER_UTIL_H_
#include <stdint.h>
#include <sys/types.h>
#include <time.h>
#include <string>
#include "base/macros.h"
#include "base/strings/string16.h"
namespace crashpad {
namespace internal {
//! \brief A collection of utility functions used by the MinidumpWritable family
//! of classes.
class MinidumpWriterUtil final {
public:
//! \brief Assigns a `time_t` value, logging a warning if the result overflows
//! the destination buffer and will be truncated.
//!
//! \param[out] destination A pointer to the variable to be assigned to.
//! \param[in] source The value to assign.
//!
//! The minidump format uses `uint32_t` for many timestamp values, but
//! `time_t` may be wider than this. These year 2038 bugs are a limitation of
//! the minidump format. An out-of-range error will be noted with a warning,
//! but is not considered fatal. \a source will be truncated and assigned to
//! \a destination in this case.
//!
//! For `time_t` values with nonfatal overflow semantics, this function is
//! used in preference to AssignIfInRange(), which fails without performing an
//! assignment when an out-of-range condition is detected.
static void AssignTimeT(uint32_t* destination, time_t source);
//! \brief Converts a UTF-8 string to UTF-16 and returns it. If the string
//! cannot be converted losslessly, indicating that the input is not
//! well-formed UTF-8, a warning is logged.
//!
//! \param[in] utf8 The UTF-8-encoded string to convert.
//!
//! \return The \a utf8 string, converted to UTF-16 encoding. If the
//! conversion is lossy, U+FFFD “replacement characters” will be
//! introduced.
static base::string16 ConvertUTF8ToUTF16(const std::string& utf8);
//! \brief Converts a UTF-8 string to UTF-16 and places it into a buffer of
//! fixed size, taking care to `NUL`-terminate the buffer and not to
//! overflow it. If the string will be truncated or if it cannot be
//! converted losslessly, a warning is logged.
//!
//! Any unused portion of the \a destination buffer that is not written to by
//! the converted string will be overwritten with `NUL` UTF-16 code units,
//! thus, this function always writes \a destination_size `char16` units.
//!
//! If the conversion is lossy, U+FFFD “replacement characters” will be
//! introduced.
//!
//! \param[out] destination A pointer to the destination buffer, where the
//! UTF-16-encoded string will be written.
//! \param[in] destination_size The size of \a destination in `char16` units,
//! including space used by a `NUL` terminator.
//! \param[in] source The UTF-8-encoded input string.
static void AssignUTF8ToUTF16(base::char16* destination,
size_t destination_size,
const std::string& source);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(MinidumpWriterUtil);
};
} // namespace internal
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_WRITER_UTIL_H_
+5
View File
@@ -0,0 +1,5 @@
Copyright (C) 1997 Gregory Pietsch
[These files] are hereby placed in the public domain without restrictions. Just
give the author credit, don't claim you wrote it or prevent anyone else from
using it.
+63
View File
@@ -0,0 +1,63 @@
/*
Copyright (C) 1997 Gregory Pietsch
[These files] are hereby placed in the public domain without restrictions. Just
give the author credit, don't claim you wrote it or prevent anyone else from
using it.
*/
#ifndef GETOPT_H
#define GETOPT_H
/* include files needed by this include file */
/* macros defined by this include file */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
/* types defined by this include file */
namespace crashpad {
/* GETOPT_LONG_OPTION_T: The type of long option */
typedef struct GETOPT_LONG_OPTION_T
{
const char *name; /* the name of the long option */
int has_arg; /* one of the above macros */
int *flag; /* determines if getopt_long() returns a
* value for a long option; if it is
* non-NULL, 0 is returned as a function
* value and the value of val is stored in
* the area pointed to by flag. Otherwise,
* val is returned. */
int val; /* determines the value to return if flag is
* NULL. */
} GETOPT_LONG_OPTION_T;
typedef GETOPT_LONG_OPTION_T option;
/* externally-defined variables */
extern char *optarg;
extern int optind;
extern int opterr;
extern int optopt;
/* function prototypes */
int getopt(int argc, char** argv, char* optstring);
int getopt_long(int argc,
char** argv,
const char* shortopts,
const GETOPT_LONG_OPTION_T* longopts,
int* longind);
int getopt_long_only(int argc,
char** argv,
const char* shortopts,
const GETOPT_LONG_OPTION_T* longopts,
int* longind);
} // namespace crashpad
#endif /* GETOPT_H */
/* END OF FILE getopt.h */
@@ -0,0 +1,198 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// For atomic operations on reference counts, see atomic_refcount.h.
// For atomic operations on sequence numbers, see atomic_sequence_num.h.
// The routines exported by this module are subtle. If you use them, even if
// you get the code right, it will depend on careful reasoning about atomicity
// and memory ordering; it will be less readable, and harder to maintain. If
// you plan to use these routines, you should have a good reason, such as solid
// evidence that performance would otherwise suffer, or there being no
// alternative. You should assume only properties explicitly guaranteed by the
// specifications in this file. You are almost certainly _not_ writing code
// just for the x86; if you assume x86 semantics, x86 hardware bugs and
// implementations on other archtectures will cause your code to break. If you
// do not know what you are doing, avoid these routines, and use a Mutex.
//
// It is incorrect to make direct assignments to/from an atomic variable.
// You should use one of the Load or Store routines. The NoBarrier
// versions are provided when no barriers are needed:
// NoBarrier_Store()
// NoBarrier_Load()
// Although there are currently no compiler enforcement, you are encouraged
// to use these.
//
#ifndef MINI_CHROMIUM_BASE_ATOMICOPS_H_
#define MINI_CHROMIUM_BASE_ATOMICOPS_H_
#include <stdint.h>
// Small C++ header which defines implementation specific macros used to
// identify the STL implementation.
// - libc++: captures __config for _LIBCPP_VERSION
// - libstdc++: captures bits/c++config.h for __GLIBCXX__
#include <cstddef>
#include "build/build_config.h"
#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
// windows.h #defines this (only on x64). This causes problems because the
// public API also uses MemoryBarrier at the public name for this fence. So, on
// X64, undef it, and call its documented
// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
// implementation directly.
#undef MemoryBarrier
#endif
namespace base {
namespace subtle {
typedef int32_t Atomic32;
#ifdef ARCH_CPU_64_BITS
// We need to be able to go between Atomic64 and AtomicWord implicitly. This
// means Atomic64 and AtomicWord should be the same type on 64-bit.
#if defined(__ILP32__) || defined(OS_NACL)
// NaCl's intptr_t is not actually 64-bits on 64-bit!
// http://code.google.com/p/nativeclient/issues/detail?id=1162
typedef int64_t Atomic64;
#else
typedef intptr_t Atomic64;
#endif
#endif
// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or
// Atomic64 routines below, depending on your architecture.
typedef intptr_t AtomicWord;
// Atomically execute:
// result = *ptr;
// if (*ptr == old_value)
// *ptr = new_value;
// return result;
//
// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
// Always return the old value of "*ptr"
//
// This routine implies no memory barriers.
Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value);
// Atomically store new_value into *ptr, returning the previous value held in
// *ptr. This routine implies no memory barriers.
Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
// Atomically increment *ptr by "increment". Returns the new value of
// *ptr with the increment applied. This routine implies no memory barriers.
Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment);
// These following lower-level operations are typically useful only to people
// implementing higher-level synchronization operations like spinlocks,
// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or
// a store with appropriate memory-ordering instructions. "Acquire" operations
// ensure that no later memory access can be reordered ahead of the operation.
// "Release" operations ensure that no previous memory access can be reordered
// after the operation. "Barrier" operations have both "Acquire" and "Release"
// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory
// access.
Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value);
Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value);
void MemoryBarrier();
void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
void Release_Store(volatile Atomic32* ptr, Atomic32 value);
Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
Atomic32 Acquire_Load(volatile const Atomic32* ptr);
Atomic32 Release_Load(volatile const Atomic32* ptr);
// 64-bit atomic operations (only available on 64-bit processors).
#ifdef ARCH_CPU_64_BITS
Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value);
Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value);
Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value);
void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
void Release_Store(volatile Atomic64* ptr, Atomic64 value);
Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
Atomic64 Acquire_Load(volatile const Atomic64* ptr);
Atomic64 Release_Load(volatile const Atomic64* ptr);
#endif // ARCH_CPU_64_BITS
} // namespace subtle
} // namespace base
// The following x86 CPU features are used in atomicops_internals_x86_gcc.h, but
// this file is duplicated inside of Chrome: protobuf and tcmalloc rely on the
// struct being present at link time. Some parts of Chrome can currently use the
// portable interface whereas others still use GCC one. The include guards are
// the same as in atomicops_internals_x86_gcc.cc.
#if defined(__i386__) || defined(__x86_64__)
// This struct is not part of the public API of this module; clients may not
// use it. (However, it's exported via BASE_EXPORT because clients implicitly
// do use it at link time by inlining these functions.)
// Features of this x86. Values may not be correct before main() is run,
// but are set conservatively.
struct AtomicOps_x86CPUFeatureStruct {
bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence
// after acquire compare-and-swap.
// The following fields are unused by Chrome's base implementation but are
// still used by copies of the same code in other parts of the code base. This
// causes an ODR violation, and the other code is likely reading invalid
// memory.
// TODO(jfb) Delete these fields once the rest of the Chrome code base doesn't
// depend on them.
bool has_sse2; // Processor has SSE2.
bool has_cmpxchg16b; // Processor supports cmpxchg16b instruction.
};
extern struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures;
#endif
// Try to use a portable implementation based on C++11 atomics.
//
// Some toolchains support C++11 language features without supporting library
// features (recent compiler, older STL). Whitelist libstdc++ and libc++ that we
// know will have <atomic> when compiling C++11.
#if ((__cplusplus >= 201103L) && \
((defined(__GLIBCXX__) && (__GLIBCXX__ > 20110216)) || \
(defined(_LIBCPP_VERSION) && (_LIBCPP_STD_VER >= 11))))
# include "base/atomicops_internals_portable.h"
#else // Otherwise use a platform specific implementation.
# if (defined(OS_WIN) && defined(COMPILER_MSVC) && \
defined(ARCH_CPU_X86_FAMILY))
# include "base/atomicops_internals_x86_msvc.h"
# elif defined(OS_MACOSX)
# include "base/atomicops_internals_mac.h"
# else
# error "Atomic operations are not supported on your platform"
# endif
#endif // Portable / non-portable includes.
// On some platforms we need additional declarations to make
// AtomicWord compatible with our other Atomic* types.
#if defined(OS_MACOSX) || defined(OS_OPENBSD)
#include "base/atomicops_internals_atomicword_compat.h"
#endif
#endif // MINI_CHROMIUM_BASE_ATOMICOPS_H_
@@ -0,0 +1,100 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is an internal atomic implementation, use base/atomicops.h instead.
#ifndef MINI_CHROMIUM_BASE_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_
#define MINI_CHROMIUM_BASE_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_
// AtomicWord is a synonym for intptr_t, and Atomic32 is a synonym for int32,
// which in turn means int. On some LP32 platforms, intptr_t is an int, but
// on others, it's a long. When AtomicWord and Atomic32 are based on different
// fundamental types, their pointers are incompatible.
//
// This file defines function overloads to allow both AtomicWord and Atomic32
// data to be used with this interface.
//
// On LP64 platforms, AtomicWord and Atomic64 are both always long,
// so this problem doesn't occur.
#if !defined(ARCH_CPU_64_BITS)
namespace base {
namespace subtle {
inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr,
AtomicWord old_value,
AtomicWord new_value) {
return NoBarrier_CompareAndSwap(
reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
}
inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr,
AtomicWord new_value) {
return NoBarrier_AtomicExchange(
reinterpret_cast<volatile Atomic32*>(ptr), new_value);
}
inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr,
AtomicWord increment) {
return NoBarrier_AtomicIncrement(
reinterpret_cast<volatile Atomic32*>(ptr), increment);
}
inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr,
AtomicWord increment) {
return Barrier_AtomicIncrement(
reinterpret_cast<volatile Atomic32*>(ptr), increment);
}
inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr,
AtomicWord old_value,
AtomicWord new_value) {
return base::subtle::Acquire_CompareAndSwap(
reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
}
inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr,
AtomicWord old_value,
AtomicWord new_value) {
return base::subtle::Release_CompareAndSwap(
reinterpret_cast<volatile Atomic32*>(ptr), old_value, new_value);
}
inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) {
NoBarrier_Store(
reinterpret_cast<volatile Atomic32*>(ptr), value);
}
inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) {
return base::subtle::Acquire_Store(
reinterpret_cast<volatile Atomic32*>(ptr), value);
}
inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) {
return base::subtle::Release_Store(
reinterpret_cast<volatile Atomic32*>(ptr), value);
}
inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) {
return NoBarrier_Load(
reinterpret_cast<volatile const Atomic32*>(ptr));
}
inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) {
return base::subtle::Acquire_Load(
reinterpret_cast<volatile const Atomic32*>(ptr));
}
inline AtomicWord Release_Load(volatile const AtomicWord* ptr) {
return base::subtle::Release_Load(
reinterpret_cast<volatile const Atomic32*>(ptr));
}
} // namespace base::subtle
} // namespace base
#endif // !defined(ARCH_CPU_64_BITS)
#endif // MINI_CHROMIUM_BASE_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_
@@ -0,0 +1,197 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is an internal atomic implementation, use base/atomicops.h instead.
#ifndef MINI_CHROMIUM_BASE_ATOMICOPS_INTERNALS_MAC_H_
#define MINI_CHROMIUM_BASE_ATOMICOPS_INTERNALS_MAC_H_
#include <libkern/OSAtomic.h>
namespace base {
namespace subtle {
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev_value;
do {
if (OSAtomicCompareAndSwap32(old_value, new_value,
const_cast<Atomic32*>(ptr))) {
return old_value;
}
prev_value = *ptr;
} while (prev_value == old_value);
return prev_value;
}
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
Atomic32 new_value) {
Atomic32 old_value;
do {
old_value = *ptr;
} while (!OSAtomicCompareAndSwap32(old_value, new_value,
const_cast<Atomic32*>(ptr)));
return old_value;
}
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr));
}
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
}
inline void MemoryBarrier() {
OSMemoryBarrier();
}
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
Atomic32 prev_value;
do {
if (OSAtomicCompareAndSwap32Barrier(old_value, new_value,
const_cast<Atomic32*>(ptr))) {
return old_value;
}
prev_value = *ptr;
} while (prev_value == old_value);
return prev_value;
}
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
return Acquire_CompareAndSwap(ptr, old_value, new_value);
}
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value;
}
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value;
MemoryBarrier();
}
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
MemoryBarrier();
*ptr = value;
}
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
return *ptr;
}
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
Atomic32 value = *ptr;
MemoryBarrier();
return value;
}
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
MemoryBarrier();
return *ptr;
}
#ifdef __LP64__
// 64-bit implementation on 64-bit platform
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
Atomic64 prev_value;
do {
if (OSAtomicCompareAndSwap64(old_value, new_value,
reinterpret_cast<volatile int64_t*>(ptr))) {
return old_value;
}
prev_value = *ptr;
} while (prev_value == old_value);
return prev_value;
}
inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
Atomic64 new_value) {
Atomic64 old_value;
do {
old_value = *ptr;
} while (!OSAtomicCompareAndSwap64(old_value, new_value,
reinterpret_cast<volatile int64_t*>(ptr)));
return old_value;
}
inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
Atomic64 increment) {
return OSAtomicAdd64(increment, reinterpret_cast<volatile int64_t*>(ptr));
}
inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
Atomic64 increment) {
return OSAtomicAdd64Barrier(increment,
reinterpret_cast<volatile int64_t*>(ptr));
}
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
Atomic64 prev_value;
do {
if (OSAtomicCompareAndSwap64Barrier(
old_value, new_value, reinterpret_cast<volatile int64_t*>(ptr))) {
return old_value;
}
prev_value = *ptr;
} while (prev_value == old_value);
return prev_value;
}
inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
// The lib kern interface does not distinguish between
// Acquire and Release memory barriers; they are equivalent.
return Acquire_CompareAndSwap(ptr, old_value, new_value);
}
inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
*ptr = value;
}
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
*ptr = value;
MemoryBarrier();
}
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
MemoryBarrier();
*ptr = value;
}
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
return *ptr;
}
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
Atomic64 value = *ptr;
MemoryBarrier();
return value;
}
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
MemoryBarrier();
return *ptr;
}
#endif // defined(__LP64__)
} // namespace base::subtle
} // namespace base
#endif // MINI_CHROMIUM_BASE_ATOMICOPS_INTERNALS_MAC_H_
@@ -0,0 +1,227 @@
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is an internal atomic implementation, use atomicops.h instead.
//
// This implementation uses C++11 atomics' member functions. The code base is
// currently written assuming atomicity revolves around accesses instead of
// C++11's memory locations. The burden is on the programmer to ensure that all
// memory locations accessed atomically are never accessed non-atomically (tsan
// should help with this).
//
// TODO(jfb) Modify the atomicops.h API and user code to declare atomic
// locations as truly atomic. See the static_assert below.
//
// Of note in this implementation:
// * All NoBarrier variants are implemented as relaxed.
// * All Barrier variants are implemented as sequentially-consistent.
// * Compare exchange's failure ordering is always the same as the success one
// (except for release, which fails as relaxed): using a weaker ordering is
// only valid under certain uses of compare exchange.
// * Acquire store doesn't exist in the C11 memory model, it is instead
// implemented as a relaxed store followed by a sequentially consistent
// fence.
// * Release load doesn't exist in the C11 memory model, it is instead
// implemented as sequentially consistent fence followed by a relaxed load.
// * Atomic increment is expected to return the post-incremented value, whereas
// C11 fetch add returns the previous value. The implementation therefore
// needs to increment twice (which the compiler should be able to detect and
// optimize).
#ifndef MINI_CHROMIUM_BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
#define MINI_CHROMIUM_BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
#include <atomic>
namespace base {
namespace subtle {
// This implementation is transitional and maintains the original API for
// atomicops.h. This requires casting memory locations to the atomic types, and
// assumes that the API and the C++11 implementation are layout-compatible,
// which isn't true for all implementations or hardware platforms. The static
// assertion should detect this issue, were it to fire then this header
// shouldn't be used.
//
// TODO(jfb) If this header manages to stay committed then the API should be
// modified, and all call sites updated.
typedef volatile std::atomic<Atomic32>* AtomicLocation32;
static_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32),
"incompatible 32-bit atomic layout");
inline void MemoryBarrier() {
#if defined(__GLIBCXX__)
// Work around libstdc++ bug 51038 where atomic_thread_fence was declared but
// not defined, leading to the linker complaining about undefined references.
__atomic_thread_fence(std::memory_order_seq_cst);
#else
std::atomic_thread_fence(std::memory_order_seq_cst);
#endif
}
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
((AtomicLocation32)ptr)
->compare_exchange_strong(old_value,
new_value,
std::memory_order_relaxed,
std::memory_order_relaxed);
return old_value;
}
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
Atomic32 new_value) {
return ((AtomicLocation32)ptr)
->exchange(new_value, std::memory_order_relaxed);
}
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
return increment +
((AtomicLocation32)ptr)
->fetch_add(increment, std::memory_order_relaxed);
}
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
return increment + ((AtomicLocation32)ptr)->fetch_add(increment);
}
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
((AtomicLocation32)ptr)
->compare_exchange_strong(old_value,
new_value,
std::memory_order_acquire,
std::memory_order_acquire);
return old_value;
}
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
((AtomicLocation32)ptr)
->compare_exchange_strong(old_value,
new_value,
std::memory_order_release,
std::memory_order_relaxed);
return old_value;
}
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
}
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
MemoryBarrier();
}
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
((AtomicLocation32)ptr)->store(value, std::memory_order_release);
}
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
}
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
return ((AtomicLocation32)ptr)->load(std::memory_order_acquire);
}
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
MemoryBarrier();
return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
}
#if defined(ARCH_CPU_64_BITS)
typedef volatile std::atomic<Atomic64>* AtomicLocation64;
static_assert(sizeof(*(AtomicLocation64) nullptr) == sizeof(Atomic64),
"incompatible 64-bit atomic layout");
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
((AtomicLocation64)ptr)
->compare_exchange_strong(old_value,
new_value,
std::memory_order_relaxed,
std::memory_order_relaxed);
return old_value;
}
inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
Atomic64 new_value) {
return ((AtomicLocation64)ptr)
->exchange(new_value, std::memory_order_relaxed);
}
inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
Atomic64 increment) {
return increment +
((AtomicLocation64)ptr)
->fetch_add(increment, std::memory_order_relaxed);
}
inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
Atomic64 increment) {
return increment + ((AtomicLocation64)ptr)->fetch_add(increment);
}
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
((AtomicLocation64)ptr)
->compare_exchange_strong(old_value,
new_value,
std::memory_order_acquire,
std::memory_order_acquire);
return old_value;
}
inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
((AtomicLocation64)ptr)
->compare_exchange_strong(old_value,
new_value,
std::memory_order_release,
std::memory_order_relaxed);
return old_value;
}
inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
}
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
MemoryBarrier();
}
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
((AtomicLocation64)ptr)->store(value, std::memory_order_release);
}
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
}
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
return ((AtomicLocation64)ptr)->load(std::memory_order_acquire);
}
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
MemoryBarrier();
return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
}
#endif // defined(ARCH_CPU_64_BITS)
}
} // namespace base::subtle
#endif // MINI_CHROMIUM_BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
@@ -0,0 +1,193 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is an internal atomic implementation, use base/atomicops.h instead.
#ifndef MINI_CHROMIUM_BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
#define MINI_CHROMIUM_BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
#include <windows.h>
#include <intrin.h>
#if defined(ARCH_CPU_64_BITS)
// windows.h #defines this (only on x64). This causes problems because the
// public API also uses MemoryBarrier at the public name for this fence. So, on
// X64, undef it, and call its documented
// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
// implementation directly.
#undef MemoryBarrier
#endif
namespace base {
namespace subtle {
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
LONG result = _InterlockedCompareExchange(
reinterpret_cast<volatile LONG*>(ptr),
static_cast<LONG>(new_value),
static_cast<LONG>(old_value));
return static_cast<Atomic32>(result);
}
inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
Atomic32 new_value) {
LONG result = _InterlockedExchange(
reinterpret_cast<volatile LONG*>(ptr),
static_cast<LONG>(new_value));
return static_cast<Atomic32>(result);
}
inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
return _InterlockedExchangeAdd(
reinterpret_cast<volatile LONG*>(ptr),
static_cast<LONG>(increment)) + increment;
}
inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment) {
return Barrier_AtomicIncrement(ptr, increment);
}
inline void MemoryBarrier() {
#if defined(ARCH_CPU_64_BITS)
// See #undef and note at the top of this file.
__faststorefence();
#else
// We use MemoryBarrier from WinNT.h
::MemoryBarrier();
#endif
}
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value;
}
inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
NoBarrier_AtomicExchange(ptr, value);
// acts as a barrier in this implementation
}
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
*ptr = value; // works w/o barrier for current Intel chips as of June 2005
// See comments in Atomic64 version of Release_Store() below.
}
inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
return *ptr;
}
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
Atomic32 value = *ptr;
return value;
}
inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
MemoryBarrier();
return *ptr;
}
#if defined(_WIN64)
// 64-bit low-level operations on 64-bit platform.
static_assert(sizeof(Atomic64) == sizeof(PVOID), "atomic word is atomic");
inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
PVOID result = InterlockedCompareExchangePointer(
reinterpret_cast<volatile PVOID*>(ptr),
reinterpret_cast<PVOID>(new_value), reinterpret_cast<PVOID>(old_value));
return reinterpret_cast<Atomic64>(result);
}
inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
Atomic64 new_value) {
PVOID result = InterlockedExchangePointer(
reinterpret_cast<volatile PVOID*>(ptr),
reinterpret_cast<PVOID>(new_value));
return reinterpret_cast<Atomic64>(result);
}
inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
Atomic64 increment) {
return InterlockedExchangeAdd64(
reinterpret_cast<volatile LONGLONG*>(ptr),
static_cast<LONGLONG>(increment)) + increment;
}
inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
Atomic64 increment) {
return Barrier_AtomicIncrement(ptr, increment);
}
inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
*ptr = value;
}
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
NoBarrier_AtomicExchange(ptr, value);
// acts as a barrier in this implementation
}
inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
*ptr = value; // works w/o barrier for current Intel chips as of June 2005
// When new chips come out, check:
// IA-32 Intel Architecture Software Developer's Manual, Volume 3:
// System Programming Guide, Chatper 7: Multiple-processor management,
// Section 7.2, Memory Ordering.
// Last seen at:
// http://developer.intel.com/design/pentium4/manuals/index_new.htm
}
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
return *ptr;
}
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
Atomic64 value = *ptr;
return value;
}
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
MemoryBarrier();
return *ptr;
}
inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
}
#endif // defined(_WIN64)
} // namespace base::subtle
} // namespace base
#endif // MINI_CHROMIUM_BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
@@ -0,0 +1,32 @@
// Copyright 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_AUTO_RESET_H_
#define MINI_CHROMIUM_BASE_AUTO_RESET_H_
#include "base/macros.h"
namespace base {
template<typename T>
class AutoReset {
public:
AutoReset(T* scoped_variable, T new_value)
: scoped_variable_(scoped_variable),
original_value_(*scoped_variable) {
*scoped_variable_ = new_value;
}
~AutoReset() { *scoped_variable_ = original_value_; }
private:
T* scoped_variable_;
T original_value_;
DISALLOW_COPY_AND_ASSIGN(AutoReset);
};
} // namespace base
#endif // MINI_CHROMIUM_BASE_AUTO_RESET_H_
@@ -0,0 +1,98 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_BIT_CAST_H_
#define MINI_CHROMIUM_BASE_BIT_CAST_H_
#include <string.h>
#include <type_traits>
#include "base/compiler_specific.h"
#include "build/build_config.h"
// bit_cast<Dest,Source> is a template function that implements the equivalent
// of "*reinterpret_cast<Dest*>(&source)". We need this in very low-level
// functions like the protobuf library and fast math support.
//
// float f = 3.14159265358979;
// int i = bit_cast<int32_t>(f);
// // i = 0x40490fdb
//
// The classical address-casting method is:
//
// // WRONG
// float f = 3.14159265358979; // WRONG
// int i = * reinterpret_cast<int*>(&f); // WRONG
//
// The address-casting method actually produces undefined behavior according to
// the ISO C++98 specification, section 3.10 ("basic.lval"), paragraph 15.
// (This did not substantially change in C++11.) Roughly, this section says: if
// an object in memory has one type, and a program accesses it with a different
// type, then the result is undefined behavior for most values of "different
// type".
//
// This is true for any cast syntax, either *(int*)&f or
// *reinterpret_cast<int*>(&f). And it is particularly true for conversions
// between integral lvalues and floating-point lvalues.
//
// The purpose of this paragraph is to allow optimizing compilers to assume that
// expressions with different types refer to different memory. Compilers are
// known to take advantage of this. So a non-conforming program quietly
// produces wildly incorrect output.
//
// The problem is not the use of reinterpret_cast. The problem is type punning:
// holding an object in memory of one type and reading its bits back using a
// different type.
//
// The C++ standard is more subtle and complex than this, but that is the basic
// idea.
//
// Anyways ...
//
// bit_cast<> calls memcpy() which is blessed by the standard, especially by the
// example in section 3.9 . Also, of course, bit_cast<> wraps up the nasty
// logic in one place.
//
// Fortunately memcpy() is very fast. In optimized mode, compilers replace
// calls to memcpy() with inline object code when the size argument is a
// compile-time constant. On a 32-bit system, memcpy(d,s,4) compiles to one
// load and one store, and memcpy(d,s,8) compiles to two loads and two stores.
template <class Dest, class Source>
inline Dest bit_cast(const Source& source) {
static_assert(sizeof(Dest) == sizeof(Source),
"bit_cast requires source and destination to be the same size");
#if (__GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) || \
defined(_LIBCPP_VERSION))
// GCC 5.1 contains the first libstdc++ with is_trivially_copyable.
// Assume libc++ Just Works: is_trivially_copyable added on May 13th 2011.
static_assert(std::is_trivially_copyable<Dest>::value,
"non-trivially-copyable bit_cast is undefined");
static_assert(std::is_trivially_copyable<Source>::value,
"non-trivially-copyable bit_cast is undefined");
#elif HAS_FEATURE(is_trivially_copyable)
// The compiler supports an equivalent intrinsic.
static_assert(__is_trivially_copyable(Dest),
"non-trivially-copyable bit_cast is undefined");
static_assert(__is_trivially_copyable(Source),
"non-trivially-copyable bit_cast is undefined");
#elif COMPILER_GCC
// Fallback to compiler intrinsic on GCC and clang (which pretends to be
// GCC). This isn't quite the same as is_trivially_copyable but it'll do for
// our purpose.
static_assert(__has_trivial_copy(Dest),
"non-trivially-copyable bit_cast is undefined");
static_assert(__has_trivial_copy(Source),
"non-trivially-copyable bit_cast is undefined");
#else
// Do nothing, let the bots handle it.
#endif
Dest dest;
memcpy(&dest, &source, sizeof(dest));
return dest;
}
#endif // MINI_CHROMIUM_BASE_BIT_CAST_H_
@@ -0,0 +1,91 @@
// Copyright 2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_COMPILER_SPECIFIC_H_
#define MINI_CHROMIUM_BASE_COMPILER_SPECIFIC_H_
#include "build/build_config.h"
#if defined(COMPILER_MSVC)
// MSVC_SUPPRESS_WARNING disables warning |n| for the remainder of the line and
// for the next line of the source file.
#define MSVC_SUPPRESS_WARNING(n) __pragma(warning(suppress:n))
// MSVC_PUSH_DISABLE_WARNING pushes |n| onto a stack of warnings to be disabled.
// The warning remains disabled until popped by MSVC_POP_WARNING.
#define MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \
__pragma(warning(disable:n))
// Pop effects of innermost MSVC_PUSH_* macro.
#define MSVC_POP_WARNING() __pragma(warning(pop))
#else // Not MSVC
#define MSVC_SUPPRESS_WARNING(n)
#define MSVC_PUSH_DISABLE_WARNING(n)
#define MSVC_POP_WARNING()
#endif // COMPILER_MSVC
// Annotate a variable indicating it's ok if the variable is not used.
// (Typically used to silence a compiler warning when the assignment
// is important for some other reason.)
// Use like:
// int x = ...;
// ALLOW_UNUSED_LOCAL(x);
#define ALLOW_UNUSED_LOCAL(x) false ? (void)x : (void)0
// Annotate a typedef or function indicating it's ok if it's not used.
// Use like:
// typedef Foo Bar ALLOW_UNUSED_TYPE;
#if defined(COMPILER_GCC)
#define ALLOW_UNUSED_TYPE __attribute__((unused))
#else
#define ALLOW_UNUSED_TYPE
#endif
// Specify memory alignment for structs, classes, etc.
// Use like:
// class ALIGNAS(16) MyClass { ... }
// ALIGNAS(16) int array[4];
#if defined(COMPILER_MSVC)
#define ALIGNAS(byte_alignment) __declspec(align(byte_alignment))
#elif defined(COMPILER_GCC)
#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
#endif
// Return the byte alignment of the given type (available at compile time). Use
// sizeof(type) prior to checking __alignof to workaround Visual C++ bug:
// http://goo.gl/isH0C
// Use like:
// ALIGNOF(int32_t) // this would be 4
#if defined(COMPILER_MSVC)
#define ALIGNOF(type) (sizeof(type) - sizeof(type) + __alignof(type))
#elif defined(COMPILER_GCC)
#define ALIGNOF(type) __alignof__(type)
#endif
#if defined(COMPILER_MSVC)
#define WARN_UNUSED_RESULT
#else
#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#endif
#if defined(COMPILER_MSVC)
#define PRINTF_FORMAT(format_param, dots_param)
#else
#define PRINTF_FORMAT(format_param, dots_param) \
__attribute__((format(printf, format_param, dots_param)))
#endif
// Compiler feature-detection.
// clang.llvm.org/docs/LanguageExtensions.html#has-feature-and-has-extension
#if defined(__has_feature)
#define HAS_FEATURE(FEATURE) __has_feature(FEATURE)
#else
#define HAS_FEATURE(FEATURE) 0
#endif
#endif // MINI_CHROMIUM_BASE_COMPILER_SPECIFIC_H_
@@ -0,0 +1,244 @@
// Copyright 2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// FilePath is a container for pathnames stored in a platform's native string
// type, providing containers for manipulation in according with the
// platform's conventions for pathnames. It supports the following path
// types:
//
// POSIX Windows
// --------------- ----------------------------------
// Fundamental type char[] wchar_t[]
// Encoding unspecified* UTF-16
// Separator / \, tolerant of /
// Drive letters no case-insensitive A-Z followed by :
// Alternate root // (surprise!) \\, for UNC paths
//
// * The encoding need not be specified on POSIX systems, although some
// POSIX-compliant systems do specify an encoding. Mac OS X uses UTF-8.
// Chrome OS also uses UTF-8.
// Linux does not specify an encoding, but in practice, the locale's
// character set may be used.
//
// For more arcane bits of path trivia, see below.
//
// FilePath objects are intended to be used anywhere paths are. An
// application may pass FilePath objects around internally, masking the
// underlying differences between systems, only differing in implementation
// where interfacing directly with the system. For example, a single
// OpenFile(const FilePath &) function may be made available, allowing all
// callers to operate without regard to the underlying implementation. On
// POSIX-like platforms, OpenFile might wrap fopen, and on Windows, it might
// wrap _wfopen_s, perhaps both by calling file_path.value().c_str(). This
// allows each platform to pass pathnames around without requiring conversions
// between encodings, which has an impact on performance, but more imporantly,
// has an impact on correctness on platforms that do not have well-defined
// encodings for pathnames.
//
// Several methods are available to perform common operations on a FilePath
// object, such as determining the parent directory (DirName), isolating the
// final path component (BaseName), and appending a relative pathname string
// to an existing FilePath object (Append). These methods are highly
// recommended over attempting to split and concatenate strings directly.
// These methods are based purely on string manipulation and knowledge of
// platform-specific pathname conventions, and do not consult the filesystem
// at all, making them safe to use without fear of blocking on I/O operations.
// These methods do not function as mutators but instead return distinct
// instances of FilePath objects, and are therefore safe to use on const
// objects. The objects themselves are safe to share between threads.
//
// To aid in initialization of FilePath objects from string literals, a
// FILE_PATH_LITERAL macro is provided, which accounts for the difference
// between char[]-based pathnames on POSIX systems and wchar_t[]-based
// pathnames on Windows.
//
// Paths can't contain NULs as a precaution agaist premature truncation.
//
// Because a FilePath object should not be instantiated at the global scope,
// instead, use a FilePath::CharType[] and initialize it with
// FILE_PATH_LITERAL. At runtime, a FilePath object can be created from the
// character array. Example:
//
// | const FilePath::CharType kLogFileName[] = FILE_PATH_LITERAL("log.txt");
// |
// | void Function() {
// | FilePath log_file_path(kLogFileName);
// | [...]
// | }
//
// WARNING: FilePaths should ALWAYS be displayed with LTR directionality, even
// when the UI language is RTL. This means you always need to pass filepaths
// through base::i18n::WrapPathWithLTRFormatting() before displaying it in the
// RTL UI.
//
// This is a very common source of bugs, please try to keep this in mind.
//
// ARCANE BITS OF PATH TRIVIA
//
// - A double leading slash is actually part of the POSIX standard. Systems
// are allowed to treat // as an alternate root, as Windows does for UNC
// (network share) paths. Most POSIX systems don't do anything special
// with two leading slashes, but FilePath handles this case properly
// in case it ever comes across such a system. FilePath needs this support
// for Windows UNC paths, anyway.
// References:
// The Open Group Base Specifications Issue 7, sections 3.266 ("Pathname")
// and 4.12 ("Pathname Resolution"), available at:
// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_266
// http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_12
//
// - Windows treats c:\\ the same way it treats \\. This was intended to
// allow older applications that require drive letters to support UNC paths
// like \\server\share\path, by permitting c:\\server\share\path as an
// equivalent. Since the OS treats these paths specially, FilePath needs
// to do the same. Since Windows can use either / or \ as the separator,
// FilePath treats c://, c:\\, //, and \\ all equivalently.
// Reference:
// The Old New Thing, "Why is a drive letter permitted in front of UNC
// paths (sometimes)?", available at:
// http://blogs.msdn.com/oldnewthing/archive/2005/11/22/495740.aspx
#ifndef MINI_CHROMIUM_BASE_FILES_FILE_PATH_H_
#define MINI_CHROMIUM_BASE_FILES_FILE_PATH_H_
#include <stddef.h>
#include <iosfwd>
#include <string>
#include "base/compiler_specific.h"
#include "build/build_config.h"
// Windows-style drive letter support and pathname separator characters can be
// enabled and disabled independently, to aid testing. These #defines are
// here so that the same setting can be used in both the implementation and
// in the unit test.
#if defined(OS_WIN)
#define FILE_PATH_USES_DRIVE_LETTERS
#define FILE_PATH_USES_WIN_SEPARATORS
#endif // OS_WIN
namespace base {
// An abstraction to isolate users from the differences between native
// pathnames on different platforms.
class FilePath {
public:
#if defined(OS_POSIX)
// On most platforms, native pathnames are char arrays, and the encoding
// may or may not be specified. On Mac OS X, native pathnames are encoded
// in UTF-8.
typedef std::string StringType;
#elif defined(OS_WIN)
// On Windows, for Unicode-aware applications, native pathnames are wchar_t
// arrays encoded in UTF-16.
typedef std::wstring StringType;
#endif // OS_WIN
typedef StringType::value_type CharType;
// Null-terminated array of separators used to separate components in
// hierarchical paths. Each character in this array is a valid separator,
// but kSeparators[0] is treated as the canonical separator and will be used
// when composing pathnames.
static const CharType kSeparators[];
// A special path component meaning "this directory."
static const CharType kCurrentDirectory[];
// A special path component meaning "the parent directory."
static const CharType kParentDirectory[];
// The character used to identify a file extension.
static const CharType kExtensionSeparator;
FilePath();
FilePath(const FilePath& that);
explicit FilePath(const StringType& path);
~FilePath();
FilePath& operator=(const FilePath& that);
bool operator==(const FilePath& that) const;
bool operator!=(const FilePath& that) const;
// Required for some STL containers and operations
bool operator<(const FilePath& that) const {
return path_ < that.path_;
}
const StringType& value() const { return path_; }
bool empty() const { return path_.empty(); }
void clear() { path_.clear(); }
// Returns true if |character| is in kSeparators.
static bool IsSeparator(CharType character);
// Returns a FilePath corresponding to the directory containing the path
// named by this object, stripping away the file component. If this object
// only contains one component, returns a FilePath identifying
// kCurrentDirectory. If this object already refers to the root directory,
// returns a FilePath identifying the root directory.
FilePath DirName() const WARN_UNUSED_RESULT;
// Returns a FilePath corresponding to the last path component of this
// object, either a file or a directory. If this object already refers to
// the root directory, returns a FilePath identifying the root directory;
// this is the only situation in which BaseName will return an absolute path.
FilePath BaseName() const WARN_UNUSED_RESULT;
// Returns the path's file extension. This does not have a special case for
// common double extensions, so FinalExtension() of "foo.tar.gz" is simply
// ".gz". If there is no extension, "" will be returned.
StringType FinalExtension() const WARN_UNUSED_RESULT;
// Returns a FilePath with FinalExtension() removed.
FilePath RemoveFinalExtension() const WARN_UNUSED_RESULT;
// Returns a FilePath by appending a separator and the supplied path
// component to this object's path. Append takes care to avoid adding
// excessive separators if this object's path already ends with a separator.
// If this object's path is kCurrentDirectory, a new FilePath corresponding
// only to |component| is returned. |component| must be a relative path;
// it is an error to pass an absolute path.
FilePath Append(const StringType& component) const WARN_UNUSED_RESULT;
FilePath Append(const FilePath& component) const WARN_UNUSED_RESULT;
// Returns true if this FilePath contains an absolute path. On Windows, an
// absolute path begins with either a drive letter specification followed by
// a separator character, or with two separator characters. On POSIX
// platforms, an absolute path begins with a separator character.
bool IsAbsolute() const;
private:
// Remove trailing separators from this object. If the path is absolute, it
// will never be stripped any more than to refer to the absolute root
// directory, so "////" will become "/", not "". A leading pair of
// separators is never stripped, to support alternate roots. This is used to
// support UNC paths on Windows.
void StripTrailingSeparatorsInternal();
StringType path_;
};
} // namespace base
// This is required by googletest to print a readable output on test failures.
extern void PrintTo(const base::FilePath& path, std::ostream* out);
// Macros for string literal initialization of FilePath::CharType[], and for
// using a FilePath::CharType[] in a printf-style format string.
#if defined(OS_POSIX)
#define FILE_PATH_LITERAL(x) x
#define PRFilePath "s"
#define PRFilePathLiteral "%s"
#elif defined(OS_WIN)
#define FILE_PATH_LITERAL(x) L ## x
#define PRFilePath "ls"
#define PRFilePathLiteral L"%ls"
#endif // OS_WIN
#endif // MINI_CHROMIUM_BASE_FILES_FILE_PATH_H_
@@ -0,0 +1,22 @@
// Copyright 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_FILES_FILE_UTIL_H_
#define MINI_CHROMIUM_BASE_FILES_FILE_UTIL_H_
#include "build/build_config.h"
#if defined(OS_POSIX)
#include <sys/types.h>
namespace base {
bool ReadFromFD(int fd, char* buffer, size_t bytes);
} // namespace base
#endif // OS_POSIX
#endif // MINI_CHROMIUM_BASE_FILES_FILE_UTIL_H_
@@ -0,0 +1,41 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_FILES_SCOPED_FILE_H_
#define MINI_CHROMIUM_BASE_FILES_SCOPED_FILE_H_
#include <stdio.h>
#include <memory>
#include "base/scoped_generic.h"
#include "build/build_config.h"
namespace base {
namespace internal {
#if defined(OS_POSIX)
struct ScopedFDCloseTraits {
static int InvalidValue() {
return -1;
}
static void Free(int fd);
};
#endif // OS_POSIX
struct ScopedFILECloser {
void operator()(FILE* file) const;
};
} // namespace internal
#if defined(OS_POSIX)
typedef ScopedGeneric<int, internal::ScopedFDCloseTraits> ScopedFD;
#endif // OS_POSIX
typedef std::unique_ptr<FILE, internal::ScopedFILECloser> ScopedFILE;
} // namespace base
#endif // MINI_CHROMIUM_BASE_FILES_SCOPED_FILE_H_
@@ -0,0 +1,101 @@
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_FORMAT_MACROS_H_
#define BASE_FORMAT_MACROS_H_
// This file defines the format macros for some integer types.
// To print a 64-bit value in a portable way:
// int64_t value;
// printf("xyz:%" PRId64, value);
// The "d" in the macro corresponds to %d; you can also use PRIu64 etc.
//
// For wide strings, prepend "Wide" to the macro:
// int64_t value;
// StringPrintf(L"xyz: %" WidePRId64, value);
//
// To print a size_t value in a portable way:
// size_t size;
// printf("xyz: %" PRIuS, size);
// The "u" in the macro corresponds to %u, and S is for "size".
#include "build/build_config.h"
#if defined(OS_POSIX)
#if (defined(_INTTYPES_H) || defined(_INTTYPES_H_)) && !defined(PRId64)
#error "inttypes.h has already been included before this header file, but "
#error "without __STDC_FORMAT_MACROS defined."
#endif
#if !defined(__STDC_FORMAT_MACROS)
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
// GCC will concatenate wide and narrow strings correctly, so nothing needs to
// be done here.
#define WidePRId64 PRId64
#define WidePRIu64 PRIu64
#define WidePRIx64 PRIx64
#if !defined(PRIuS)
#define PRIuS "zu"
#endif
// The size of NSInteger and NSUInteger varies between 32-bit and 64-bit
// architectures and Apple does not provides standard format macros and
// recommends casting. This has many drawbacks, so instead define macros
// for formatting those types.
#if defined(OS_MACOSX)
#if defined(ARCH_CPU_64_BITS)
#if !defined(PRIdNS)
#define PRIdNS "ld"
#endif
#if !defined(PRIuNS)
#define PRIuNS "lu"
#endif
#if !defined(PRIxNS)
#define PRIxNS "lx"
#endif
#else // defined(ARCH_CPU_64_BITS)
#if !defined(PRIdNS)
#define PRIdNS "d"
#endif
#if !defined(PRIuNS)
#define PRIuNS "u"
#endif
#if !defined(PRIxNS)
#define PRIxNS "x"
#endif
#endif
#endif // defined(OS_MACOSX)
#else // OS_WIN
#if !defined(PRId64)
#define PRId64 "I64d"
#endif
#if !defined(PRIu64)
#define PRIu64 "I64u"
#endif
#if !defined(PRIx64)
#define PRIx64 "I64x"
#endif
#define WidePRId64 L"I64d"
#define WidePRIu64 L"I64u"
#define WidePRIx64 L"I64x"
#if !defined(PRIuS)
#define PRIuS "Iu"
#endif
#endif
#endif // BASE_FORMAT_MACROS_H_
@@ -0,0 +1,353 @@
// Copyright 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_LOGGING_H_
#define MINI_CHROMIUM_BASE_LOGGING_H_
#include <assert.h>
#include <errno.h>
#include <limits>
#include <sstream>
#include <string>
#include "base/macros.h"
#include "build/build_config.h"
namespace logging {
typedef int LogSeverity;
const LogSeverity LOG_VERBOSE = -1;
const LogSeverity LOG_INFO = 0;
const LogSeverity LOG_WARNING = 1;
const LogSeverity LOG_ERROR = 2;
const LogSeverity LOG_ERROR_REPORT = 3;
const LogSeverity LOG_FATAL = 4;
const LogSeverity LOG_NUM_SEVERITIES = 5;
#if defined(NDEBUG)
const LogSeverity LOG_DFATAL = LOG_ERROR;
#else
const LogSeverity LOG_DFATAL = LOG_FATAL;
#endif
typedef bool (*LogMessageHandlerFunction)(LogSeverity severity,
const char* file_poath,
int line,
size_t message_start,
const std::string& string);
void SetLogMessageHandler(LogMessageHandlerFunction log_message_handler);
LogMessageHandlerFunction GetLogMessageHandler();
static inline int GetMinLogLevel() {
return LOG_INFO;
}
static inline int GetVlogLevel(const char*) {
return std::numeric_limits<int>::max();
}
#if defined(OS_WIN)
// This is just ::GetLastError, but out-of-line to avoid including windows.h in
// such a widely used place.
unsigned long GetLastSystemErrorCode();
std::string SystemErrorCodeToString(unsigned long error_code);
#elif defined(OS_POSIX)
static inline int GetLastSystemErrorCode() {
return errno;
}
#endif
template<typename t1, typename t2>
std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) {
std::ostringstream ss;
ss << names << " (" << v1 << " vs. " << v2 << ")";
std::string* msg = new std::string(ss.str());
return msg;
}
#define DEFINE_CHECK_OP_IMPL(name, op) \
template <typename t1, typename t2> \
inline std::string* Check ## name ## Impl(const t1& v1, const t2& v2, \
const char* names) { \
if (v1 op v2) { \
return NULL; \
} else { \
return MakeCheckOpString(v1, v2, names); \
} \
} \
inline std::string* Check ## name ## Impl(int v1, int v2, \
const char* names) { \
if (v1 op v2) { \
return NULL; \
} else { \
return MakeCheckOpString(v1, v2, names); \
} \
}
DEFINE_CHECK_OP_IMPL(EQ, ==)
DEFINE_CHECK_OP_IMPL(NE, !=)
DEFINE_CHECK_OP_IMPL(LE, <=)
DEFINE_CHECK_OP_IMPL(LT, <)
DEFINE_CHECK_OP_IMPL(GE, >=)
DEFINE_CHECK_OP_IMPL(GT, >)
#undef DEFINE_CHECK_OP_IMPL
class LogMessage {
public:
LogMessage(const char* function,
const char* file_path,
int line,
LogSeverity severity);
LogMessage(const char* function,
const char* file_path,
int line,
std::string* result);
~LogMessage();
std::ostream& stream() { return stream_; }
private:
void Init(const char* function);
std::ostringstream stream_;
const char* file_path_;
size_t message_start_;
const int line_;
LogSeverity severity_;
DISALLOW_COPY_AND_ASSIGN(LogMessage);
};
class LogMessageVoidify {
public:
LogMessageVoidify() {}
void operator&(const std::ostream&) const {}
};
#if defined(OS_WIN)
class Win32ErrorLogMessage : public LogMessage {
public:
Win32ErrorLogMessage(const char* function,
const char* file_path,
int line,
LogSeverity severity,
unsigned long err);
~Win32ErrorLogMessage();
private:
unsigned long err_;
DISALLOW_COPY_AND_ASSIGN(Win32ErrorLogMessage);
};
#elif defined(OS_POSIX)
class ErrnoLogMessage : public LogMessage {
public:
ErrnoLogMessage(const char* function,
const char* file_path,
int line,
LogSeverity severity,
int err);
~ErrnoLogMessage();
private:
int err_;
DISALLOW_COPY_AND_ASSIGN(ErrnoLogMessage);
};
#endif
} // namespace logging
#if defined(COMPILER_MSVC)
#define FUNCTION_SIGNATURE __FUNCSIG__
#else
#define FUNCTION_SIGNATURE __PRETTY_FUNCTION__
#endif
#define COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...) \
logging::ClassName(FUNCTION_SIGNATURE, __FILE__, __LINE__, \
logging::LOG_INFO, ## __VA_ARGS__)
#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \
logging::ClassName(FUNCTION_SIGNATURE, __FILE__, __LINE__, \
logging::LOG_WARNING, ## __VA_ARGS__)
#define COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...) \
logging::ClassName(FUNCTION_SIGNATURE, __FILE__, __LINE__, \
logging::LOG_ERROR, ## __VA_ARGS__)
#define COMPACT_GOOGLE_LOG_EX_ERROR_REPORT(ClassName, ...) \
logging::ClassName(FUNCTION_SIGNATURE, __FILE__, __LINE__, \
logging::LOG_ERROR_REPORT, ## __VA_ARGS__)
#define COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...) \
logging::ClassName(FUNCTION_SIGNATURE, __FILE__, __LINE__, \
logging::LOG_FATAL, ## __VA_ARGS__)
#define COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...) \
logging::ClassName(FUNCTION_SIGNATURE, __FILE__, __LINE__, \
logging::LOG_DFATAL, ## __VA_ARGS__)
#define COMPACT_GOOGLE_LOG_INFO \
COMPACT_GOOGLE_LOG_EX_INFO(LogMessage)
#define COMPACT_GOOGLE_LOG_WARNING \
COMPACT_GOOGLE_LOG_EX_WARNING(LogMessage)
#define COMPACT_GOOGLE_LOG_ERROR \
COMPACT_GOOGLE_LOG_EX_ERROR(LogMessage)
#define COMPACT_GOOGLE_LOG_ERROR_REPORT \
COMPACT_GOOGLE_LOG_EX_ERROR_REPORT(LogMessage)
#define COMPACT_GOOGLE_LOG_FATAL \
COMPACT_GOOGLE_LOG_EX_FATAL(LogMessage)
#define COMPACT_GOOGLE_LOG_DFATAL \
COMPACT_GOOGLE_LOG_EX_DFATAL(LogMessage)
#if defined(OS_WIN)
// wingdi.h defines ERROR 0. We don't want to include windows.h here, and we
// want to allow "LOG(ERROR)", which will expand to LOG_0.
// This will not cause a warning if the RHS text is identical to that in
// wingdi.h (which it is).
#define ERROR 0
#define COMPACT_GOOGLE_LOG_EX_0(ClassName, ...) \
COMPACT_GOOGLE_LOG_EX_ERROR(ClassName , ##__VA_ARGS__)
#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR
namespace logging {
const LogSeverity LOG_0 = LOG_ERROR;
} // namespace logging
#endif // OS_WIN
#define LAZY_STREAM(stream, condition) \
!(condition) ? (void) 0 : ::logging::LogMessageVoidify() & (stream)
#define LOG_IS_ON(severity) \
((::logging::LOG_ ## severity) >= ::logging::GetMinLogLevel())
#define VLOG_IS_ON(verbose_level) \
((verbose_level) <= ::logging::GetVlogLevel(__FILE__))
#define LOG_STREAM(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()
#define VLOG_STREAM(verbose_level) \
logging::LogMessage(FUNCTION_SIGNATURE, __FILE__, __LINE__, \
-verbose_level).stream()
#if defined(OS_WIN)
#define PLOG_STREAM(severity) COMPACT_GOOGLE_LOG_EX_ ## severity( \
Win32ErrorLogMessage, ::logging::GetLastSystemErrorCode()).stream()
#define VPLOG_STREAM(verbose_level) \
logging::Win32ErrorLogMessage(FUNCTION_SIGNATURE, __FILE__, __LINE__, \
-verbose_level, \
::logging::GetLastSystemErrorCode()).stream()
#elif defined(OS_POSIX)
#define PLOG_STREAM(severity) COMPACT_GOOGLE_LOG_EX_ ## severity( \
ErrnoLogMessage, ::logging::GetLastSystemErrorCode()).stream()
#define VPLOG_STREAM(verbose_level) \
logging::ErrnoLogMessage(FUNCTION_SIGNATURE, __FILE__, __LINE__, \
-verbose_level, \
::logging::GetLastSystemErrorCode()).stream()
#endif
#define LOG(severity) LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity))
#define LOG_IF(severity, condition) \
LAZY_STREAM(LOG_STREAM(severity), LOG_IS_ON(severity) && (condition))
#define LOG_ASSERT(condition) \
LOG_IF(FATAL, !(condition)) << "Assertion failed: " # condition ". "
#define VLOG(verbose_level) \
LAZY_STREAM(VLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level))
#define VLOG_IF(verbose_level, condition) \
LAZY_STREAM(VLOG_STREAM(verbose_level), \
VLOG_IS_ON(verbose_level) && (condition))
#define PLOG(severity) LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity))
#define PLOG_IF(severity, condition) \
LAZY_STREAM(PLOG_STREAM(severity), LOG_IS_ON(severity) && (condition))
#define VPLOG(verbose_level) \
LAZY_STREAM(VPLOG_STREAM(verbose_level), VLOG_IS_ON(verbose_level))
#define VPLOG_IF(verbose_level, condition) \
LAZY_STREAM(VPLOG_STREAM(verbose_level), \
VLOG_IS_ON(verbose_level) && (condition))
#define CHECK(condition) \
LAZY_STREAM(LOG_STREAM(FATAL), !(condition)) \
<< "Check failed: " # condition << ". "
#define PCHECK(condition) \
LAZY_STREAM(PLOG_STREAM(FATAL), !(condition)) \
<< "Check failed: " # condition << ". "
#define CHECK_OP(name, op, val1, val2) \
if (std::string* _result = \
logging::Check ## name ## Impl((val1), (val2), \
# val1 " " # op " " # val2)) \
logging::LogMessage(FUNCTION_SIGNATURE, __FILE__, __LINE__, \
_result).stream()
#define CHECK_EQ(val1, val2) CHECK_OP(EQ, ==, val1, val2)
#define CHECK_NE(val1, val2) CHECK_OP(NE, !=, val1, val2)
#define CHECK_LE(val1, val2) CHECK_OP(LE, <=, val1, val2)
#define CHECK_LT(val1, val2) CHECK_OP(LT, <, val1, val2)
#define CHECK_GE(val1, val2) CHECK_OP(GE, >=, val1, val2)
#define CHECK_GT(val1, val2) CHECK_OP(GT, >, val1, val2)
#if defined(NDEBUG)
#define DLOG_IS_ON(severity) 0
#define DVLOG_IS_ON(verbose_level) 0
#define DCHECK_IS_ON() 0
#else
#define DLOG_IS_ON(severity) LOG_IS_ON(severity)
#define DVLOG_IS_ON(verbose_level) VLOG_IS_ON(verbose_level)
#define DCHECK_IS_ON() 1
#endif
#define DLOG(severity) LAZY_STREAM(LOG_STREAM(severity), DLOG_IS_ON(severity))
#define DLOG_IF(severity, condition) \
LAZY_STREAM(LOG_STREAM(severity), DLOG_IS_ON(severity) && (condition))
#define DLOG_ASSERT(condition) \
DLOG_IF(FATAL, !(condition)) << "Assertion failed: " # condition ". "
#define DVLOG(verbose_level) \
LAZY_STREAM(VLOG_STREAM(verbose_level), DVLOG_IS_ON(verbose_level))
#define DVLOG_IF(verbose_level, condition) \
LAZY_STREAM(VLOG_STREAM(verbose_level), \
DVLOG_IS_ON(verbose_level) && (condition))
#define DPLOG(severity) LAZY_STREAM(PLOG_STREAM(severity), DLOG_IS_ON(severity))
#define DPLOG_IF(severity, condition) \
LAZY_STREAM(PLOG_STREAM(severity), DLOG_IS_ON(severity) && (condition))
#define DVPLOG(verbose_level) \
LAZY_STREAM(VPLOG_STREAM(verbose_level), DVLOG_IS_ON(verbose_level))
#define DVPLOG_IF(verbose_level, condition) \
LAZY_STREAM(VPLOG_STREAM(verbose_level), \
DVLOG_IS_ON(verbose_level) && (condition))
#define DCHECK(condition) \
LAZY_STREAM(LOG_STREAM(FATAL), DCHECK_IS_ON() ? !(condition) : false) \
<< "Check failed: " # condition << ". "
#define DPCHECK(condition) \
LAZY_STREAM(PLOG_STREAM(FATAL), DCHECK_IS_ON() ? !(condition) : false) \
<< "Check failed: " # condition << ". "
#define DCHECK_OP(name, op, val1, val2) \
if (DCHECK_IS_ON()) \
if (std::string* _result = \
logging::Check ## name ## Impl((val1), (val2), \
# val1 " " # op " " # val2)) \
logging::LogMessage(FUNCTION_SIGNATURE, __FILE__, __LINE__, \
_result).stream()
#define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2)
#define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2)
#define DCHECK_LE(val1, val2) DCHECK_OP(LE, <=, val1, val2)
#define DCHECK_LT(val1, val2) DCHECK_OP(LT, <, val1, val2)
#define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2)
#define DCHECK_GT(val1, val2) DCHECK_OP(GT, >, val1, val2)
#define NOTREACHED() DCHECK(false)
#undef assert
#define assert(condition) DLOG_ASSERT(condition)
#endif // MINI_CHROMIUM_BASE_LOGGING_H_
@@ -0,0 +1,181 @@
// Copyright 2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MINI_CHROMIUM_BASE_MAC_FOUNDATION_UTIL_H_
#define MINI_CHROMIUM_BASE_MAC_FOUNDATION_UTIL_H_
#include <ApplicationServices/ApplicationServices.h>
#include "base/logging.h"
#if defined(__OBJC__)
#import <Foundation/Foundation.h>
#else // defined(__OBJC__)
#include <CoreFoundation/CoreFoundation.h>
#endif // defined(__OBJC__)
#if !defined(__OBJC__)
#define OBJC_CPP_CLASS_DECL(x) class x;
#else // defined(__OBJC__)
#define OBJC_CPP_CLASS_DECL(x)
#endif // defined(__OBJC__)
// Convert toll-free bridged CFTypes to NSTypes and vice-versa. This does not
// autorelease |cf_val|. This is useful for the case where there is a CFType in
// a call that expects an NSType and the compiler is complaining about const
// casting problems.
// The calls are used like this:
// NSString *foo = CFToNSCast(CFSTR("Hello"));
// CFStringRef foo2 = NSToCFCast(@"Hello");
// The macro magic below is to enforce safe casting. It could possibly have
// been done using template function specialization, but template function
// specialization doesn't always work intuitively,
// (http://www.gotw.ca/publications/mill17.htm) so the trusty combination
// of macros and function overloading is used instead.
#define CF_TO_NS_CAST_DECL(TypeCF, TypeNS) \
OBJC_CPP_CLASS_DECL(TypeNS) \
\
namespace base { \
namespace mac { \
TypeNS* CFToNSCast(TypeCF##Ref cf_val); \
TypeCF##Ref NSToCFCast(TypeNS* ns_val); \
} \
}
#define CF_TO_NS_MUTABLE_CAST_DECL(name) \
CF_TO_NS_CAST_DECL(CF##name, NS##name) \
OBJC_CPP_CLASS_DECL(NSMutable##name) \
\
namespace base { \
namespace mac { \
NSMutable##name* CFToNSCast(CFMutable##name##Ref cf_val); \
CFMutable##name##Ref NSToCFCast(NSMutable##name* ns_val); \
} \
}
// List of toll-free bridged types taken from:
// http://www.cocoadev.com/index.pl?TollFreeBridged
CF_TO_NS_MUTABLE_CAST_DECL(Array);
CF_TO_NS_MUTABLE_CAST_DECL(AttributedString);
CF_TO_NS_CAST_DECL(CFCalendar, NSCalendar);
CF_TO_NS_MUTABLE_CAST_DECL(CharacterSet);
CF_TO_NS_MUTABLE_CAST_DECL(Data);
CF_TO_NS_CAST_DECL(CFDate, NSDate);
CF_TO_NS_MUTABLE_CAST_DECL(Dictionary);
CF_TO_NS_CAST_DECL(CFError, NSError);
CF_TO_NS_CAST_DECL(CFLocale, NSLocale);
CF_TO_NS_CAST_DECL(CFNumber, NSNumber);
CF_TO_NS_CAST_DECL(CFRunLoopTimer, NSTimer);
CF_TO_NS_CAST_DECL(CFTimeZone, NSTimeZone);
CF_TO_NS_MUTABLE_CAST_DECL(Set);
CF_TO_NS_CAST_DECL(CFReadStream, NSInputStream);
CF_TO_NS_CAST_DECL(CFWriteStream, NSOutputStream);
CF_TO_NS_MUTABLE_CAST_DECL(String);
CF_TO_NS_CAST_DECL(CFURL, NSURL);
#undef CF_TO_NS_CAST_DECL
#undef CF_TO_NS_MUTABLE_CAST_DECL
#undef OBJC_CPP_CLASS_DECL
namespace base {
namespace mac {
// CFCast<>() and CFCastStrict<>() cast a basic CFTypeRef to a more
// specific CoreFoundation type. The compatibility of the passed
// object is found by comparing its opaque type against the
// requested type identifier. If the supplied object is not
// compatible with the requested return type, CFCast<>() returns
// NULL and CFCastStrict<>() will DCHECK. Providing a NULL pointer
// to either variant results in NULL being returned without
// triggering any DCHECK.
//
// Example usage:
// CFNumberRef some_number = base::mac::CFCast<CFNumberRef>(
// CFArrayGetValueAtIndex(array, index));
//
// CFTypeRef hello = CFSTR("hello world");
// CFStringRef some_string = base::mac::CFCastStrict<CFStringRef>(hello);
template<typename T>
T CFCast(const CFTypeRef& cf_val);
template<typename T>
T CFCastStrict(const CFTypeRef& cf_val);
#define CF_CAST_DECL(TypeCF) \
template<> TypeCF##Ref \
CFCast<TypeCF##Ref>(const CFTypeRef& cf_val);\
\
template<> TypeCF##Ref \
CFCastStrict<TypeCF##Ref>(const CFTypeRef& cf_val);
CF_CAST_DECL(CFArray);
CF_CAST_DECL(CFBag);
CF_CAST_DECL(CFBoolean);
CF_CAST_DECL(CFData);
CF_CAST_DECL(CFDate);
CF_CAST_DECL(CFDictionary);
CF_CAST_DECL(CFNull);
CF_CAST_DECL(CFNumber);
CF_CAST_DECL(CFSet);
CF_CAST_DECL(CFString);
CF_CAST_DECL(CFURL);
CF_CAST_DECL(CFUUID);
CF_CAST_DECL(CGColor);
CF_CAST_DECL(CTFont);
CF_CAST_DECL(CTRun);
CF_CAST_DECL(SecACL);
CF_CAST_DECL(SecTrustedApplication);
#undef CF_CAST_DECL
#if defined(__OBJC__)
// ObjCCast<>() and ObjCCastStrict<>() cast a basic id to a more
// specific (NSObject-derived) type. The compatibility of the passed
// object is found by checking if it's a kind of the requested type
// identifier. If the supplied object is not compatible with the
// requested return type, ObjCCast<>() returns nil and
// ObjCCastStrict<>() will DCHECK. Providing a nil pointer to either
// variant results in nil being returned without triggering any DCHECK.
//
// The strict variant is useful when retrieving a value from a
// collection which only has values of a specific type, e.g. an
// NSArray of NSStrings. The non-strict variant is useful when
// retrieving values from data that you can't fully control. For
// example, a plist read from disk may be beyond your exclusive
// control, so you'd only want to check that the values you retrieve
// from it are of the expected types, but not crash if they're not.
//
// Example usage:
// NSString* version = base::mac::ObjCCast<NSString>(
// [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]);
//
// NSString* str = base::mac::ObjCCastStrict<NSString>(
// [ns_arr_of_ns_strs objectAtIndex:0]);
template<typename T>
T* ObjCCast(id objc_val) {
if ([objc_val isKindOfClass:[T class]]) {
return reinterpret_cast<T*>(objc_val);
}
return nil;
}
template<typename T>
T* ObjCCastStrict(id objc_val) {
T* rv = ObjCCast<T>(objc_val);
DCHECK(objc_val == nil || rv);
return rv;
}
#endif // defined(__OBJC__)
} // namespace mac
} // namespace base
#endif // MINI_CHROMIUM_BASE_MAC_FOUNDATION_UTIL_H_

Some files were not shown because too many files have changed in this diff Show More