mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-27 15:32:10 +08:00
snapshot: Add a minimal ModuleSnapshotMinidump and accessor from
ProcessSnapshotMinidump. ModuleSnapshotMinidump is currently only capable of reading module annotations, in both vector and simple-dictionary forms. It does not read any other module information from minidump files. These annotations are all that are necessary to be able to upload Crashpad-produced minidumps to Breakpad crash processor servers, because Breakpad accepts them as HTTP POST parameters, while Crashpad places them in the minidump file itself. TEST=snapshot_test ProcessSnapshotMinidump.Modules BUG=crashpad:10 R=rsesek@chromium.org Review URL: https://codereview.chromium.org/972383002
This commit is contained in:
parent
4539fd1553
commit
445c0eae7c
@ -136,6 +136,7 @@ void ModuleSnapshotMac::UUID(crashpad::UUID* uuid) const {
|
||||
}
|
||||
|
||||
std::vector<std::string> ModuleSnapshotMac::AnnotationsVector() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
MachOImageAnnotationsReader annotations_reader(
|
||||
process_reader_, mach_o_image_reader_, name_);
|
||||
return annotations_reader.Vector();
|
||||
@ -143,6 +144,7 @@ std::vector<std::string> ModuleSnapshotMac::AnnotationsVector() const {
|
||||
|
||||
std::map<std::string, std::string> ModuleSnapshotMac::AnnotationsSimpleMap()
|
||||
const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
MachOImageAnnotationsReader annotations_reader(
|
||||
process_reader_, mach_o_image_reader_, name_);
|
||||
return annotations_reader.SimpleMap();
|
||||
|
@ -144,10 +144,9 @@ void ProcessSnapshotMac::InitializeThreads() {
|
||||
process_reader_.Threads();
|
||||
for (const ProcessReader::Thread& process_reader_thread :
|
||||
process_reader_threads) {
|
||||
internal::ThreadSnapshotMac* thread = new internal::ThreadSnapshotMac();
|
||||
threads_.push_back(thread);
|
||||
if (!thread->Initialize(&process_reader_, process_reader_thread)) {
|
||||
threads_.pop_back();
|
||||
auto thread = make_scoped_ptr(new internal::ThreadSnapshotMac());
|
||||
if (thread->Initialize(&process_reader_, process_reader_thread)) {
|
||||
threads_.push_back(thread.release());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -157,10 +156,9 @@ void ProcessSnapshotMac::InitializeModules() {
|
||||
process_reader_.Modules();
|
||||
for (const ProcessReader::Module& process_reader_module :
|
||||
process_reader_modules) {
|
||||
internal::ModuleSnapshotMac* module = new internal::ModuleSnapshotMac();
|
||||
modules_.push_back(module);
|
||||
if (!module->Initialize(&process_reader_, process_reader_module)) {
|
||||
modules_.pop_back();
|
||||
auto module = make_scoped_ptr(new internal::ModuleSnapshotMac());
|
||||
if (module->Initialize(&process_reader_, process_reader_module)) {
|
||||
modules_.push_back(module.release());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,8 @@ bool ReadMinidumpSimpleStringDictionary(
|
||||
}
|
||||
|
||||
if (location.DataSize !=
|
||||
entry_count * sizeof(MinidumpSimpleStringDictionaryEntry)) {
|
||||
sizeof(MinidumpSimpleStringDictionary) +
|
||||
entry_count * sizeof(MinidumpSimpleStringDictionaryEntry)) {
|
||||
LOG(ERROR) << "simple_string_dictionary size mismatch";
|
||||
return false;
|
||||
}
|
||||
@ -63,19 +64,17 @@ bool ReadMinidumpSimpleStringDictionary(
|
||||
for (const MinidumpSimpleStringDictionaryEntry& entry : entries) {
|
||||
std::string key;
|
||||
if (!ReadMinidumpUTF8String(file_reader, entry.key, &key)) {
|
||||
// Not a hard error, keep trying.
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string value;
|
||||
if (!ReadMinidumpUTF8String(file_reader, entry.value, &value)) {
|
||||
// Not a hard error, keep trying.
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (local_dictionary.find(key) != local_dictionary.end()) {
|
||||
LOG(WARNING) << "duplicate key " << key << ", discarding value " << value;
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
|
||||
local_dictionary.insert(std::make_pair(key, value));
|
||||
|
@ -30,9 +30,7 @@ namespace internal {
|
||||
//! location in \a file_reader, and returns it in \a dictionary.
|
||||
//!
|
||||
//! \return `true` on success, with \a dictionary set by replacing its contents.
|
||||
//! `false` on failure, with a message logged. If any individual strings
|
||||
//! cannot be read, or if any duplicate keys are found, it is not considered
|
||||
//! an error, although a message will be logged.
|
||||
//! `false` on failure, with a message logged.
|
||||
bool ReadMinidumpSimpleStringDictionary(
|
||||
FileReaderInterface* file_reader,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location,
|
||||
|
72
snapshot/minidump/minidump_string_list_reader.cc
Normal file
72
snapshot/minidump/minidump_string_list_reader.cc
Normal file
@ -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.
|
||||
|
||||
#include "snapshot/minidump/minidump_string_list_reader.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "minidump/minidump_extensions.h"
|
||||
#include "snapshot/minidump/minidump_string_reader.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace internal {
|
||||
|
||||
bool ReadMinidumpStringList(FileReaderInterface* file_reader,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location,
|
||||
std::vector<std::string>* list) {
|
||||
if (location.Rva == 0) {
|
||||
list->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (location.DataSize < sizeof(MinidumpRVAList)) {
|
||||
LOG(ERROR) << "string_list size mismatch";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_reader->SeekSet(location.Rva)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t entry_count;
|
||||
if (!file_reader->ReadExactly(&entry_count, sizeof(entry_count))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (location.DataSize !=
|
||||
sizeof(MinidumpRVAList) + entry_count * sizeof(RVA)) {
|
||||
LOG(ERROR) << "string_list size mismatch";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<RVA> rvas(entry_count);
|
||||
if (!file_reader->ReadExactly(&rvas[0], entry_count * sizeof(rvas[0]))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> local_list;
|
||||
for (RVA rva : rvas) {
|
||||
std::string element;
|
||||
if (!ReadMinidumpUTF8String(file_reader, rva, &element)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
local_list.push_back(element);
|
||||
}
|
||||
|
||||
list->swap(local_list);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace crashpad
|
42
snapshot/minidump/minidump_string_list_reader.h
Normal file
42
snapshot/minidump/minidump_string_list_reader.h
Normal file
@ -0,0 +1,42 @@
|
||||
// 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_SNAPSHOT_MINIDUMP_MINIDUMP_STRING_LIST_READER_H_
|
||||
#define CRASHPAD_SNAPSHOT_MINIDUMP_MINIDUMP_STRING_LIST_READER_H_
|
||||
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "util/file/file_reader.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace internal {
|
||||
|
||||
//! \brief Reads a list of MinidumpUTF8String objects in a MinidumpRVAList from
|
||||
//! a minidump file \a location in \a file_reader, and returns it in \a
|
||||
//! list.
|
||||
//!
|
||||
//! \return `true` on success, with \a list set by replacing its contents.
|
||||
//! `false` on failure, with a message logged.
|
||||
bool ReadMinidumpStringList(FileReaderInterface* file_reader,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR& location,
|
||||
std::vector<std::string>* list);
|
||||
|
||||
} // namespace internal
|
||||
} // namespace crashpad
|
||||
|
||||
#endif // CRASHPAD_SNAPSHOT_MINIDUMP_MINIDUMP_STRING_LIST_READER_H_
|
174
snapshot/minidump/module_snapshot_minidump.cc
Normal file
174
snapshot/minidump/module_snapshot_minidump.cc
Normal file
@ -0,0 +1,174 @@
|
||||
// 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.
|
||||
|
||||
#include "snapshot/minidump/module_snapshot_minidump.h"
|
||||
|
||||
#include "minidump/minidump_extensions.h"
|
||||
#include "snapshot/minidump/minidump_simple_string_dictionary_reader.h"
|
||||
#include "snapshot/minidump/minidump_string_list_reader.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace internal {
|
||||
|
||||
ModuleSnapshotMinidump::ModuleSnapshotMinidump()
|
||||
: ModuleSnapshot(),
|
||||
minidump_module_(),
|
||||
annotations_vector_(),
|
||||
annotations_simple_map_(),
|
||||
initialized_() {
|
||||
}
|
||||
|
||||
ModuleSnapshotMinidump::~ModuleSnapshotMinidump() {
|
||||
}
|
||||
|
||||
bool ModuleSnapshotMinidump::Initialize(
|
||||
FileReaderInterface* file_reader,
|
||||
RVA minidump_module_rva,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR*
|
||||
minidump_module_crashpad_info_location) {
|
||||
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
||||
|
||||
if (!file_reader->SeekSet(minidump_module_rva)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_reader->ReadExactly(&minidump_module_, sizeof(minidump_module_))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!InitializeModuleCrashpadInfo(file_reader,
|
||||
minidump_module_crashpad_info_location)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string ModuleSnapshotMinidump::Name() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
return std::string();
|
||||
}
|
||||
|
||||
uint64_t ModuleSnapshotMinidump::Address() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t ModuleSnapshotMinidump::Size() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
return 0;
|
||||
}
|
||||
|
||||
time_t ModuleSnapshotMinidump::Timestamp() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ModuleSnapshotMinidump::FileVersion(uint16_t* version_0,
|
||||
uint16_t* version_1,
|
||||
uint16_t* version_2,
|
||||
uint16_t* version_3) const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
*version_0 = 0;
|
||||
*version_1 = 0;
|
||||
*version_2 = 0;
|
||||
*version_3 = 0;
|
||||
}
|
||||
|
||||
void ModuleSnapshotMinidump::SourceVersion(uint16_t* version_0,
|
||||
uint16_t* version_1,
|
||||
uint16_t* version_2,
|
||||
uint16_t* version_3) const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
*version_0 = 0;
|
||||
*version_1 = 0;
|
||||
*version_2 = 0;
|
||||
*version_3 = 0;
|
||||
}
|
||||
|
||||
ModuleSnapshot::ModuleType ModuleSnapshotMinidump::GetModuleType() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
return kModuleTypeUnknown;
|
||||
}
|
||||
|
||||
void ModuleSnapshotMinidump::UUID(crashpad::UUID* uuid) const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
*uuid = crashpad::UUID();
|
||||
}
|
||||
|
||||
std::vector<std::string> ModuleSnapshotMinidump::AnnotationsVector() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
return annotations_vector_;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string>
|
||||
ModuleSnapshotMinidump::AnnotationsSimpleMap() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
return annotations_simple_map_;
|
||||
}
|
||||
|
||||
bool ModuleSnapshotMinidump::InitializeModuleCrashpadInfo(
|
||||
FileReaderInterface* file_reader,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR*
|
||||
minidump_module_crashpad_info_location) {
|
||||
if (!minidump_module_crashpad_info_location ||
|
||||
minidump_module_crashpad_info_location->Rva == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
MinidumpModuleCrashpadInfo minidump_module_crashpad_info;
|
||||
if (minidump_module_crashpad_info_location->DataSize <
|
||||
sizeof(minidump_module_crashpad_info)) {
|
||||
LOG(ERROR) << "minidump_module_crashpad_info size mismatch";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_reader->SeekSet(minidump_module_crashpad_info_location->Rva)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_reader->ReadExactly(&minidump_module_crashpad_info,
|
||||
sizeof(minidump_module_crashpad_info))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (minidump_module_crashpad_info.version !=
|
||||
MinidumpModuleCrashpadInfo::kVersion) {
|
||||
LOG(ERROR) << "minidump_module_crashpad_info version mismatch";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ReadMinidumpStringList(file_reader,
|
||||
minidump_module_crashpad_info.list_annotations,
|
||||
&annotations_vector_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ReadMinidumpSimpleStringDictionary(
|
||||
file_reader,
|
||||
minidump_module_crashpad_info.simple_annotations,
|
||||
&annotations_simple_map_);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace crashpad
|
97
snapshot/minidump/module_snapshot_minidump.h
Normal file
97
snapshot/minidump/module_snapshot_minidump.h
Normal file
@ -0,0 +1,97 @@
|
||||
// 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_SNAPSHOT_MINIDUMP_MODULE_SNAPSHOT_MINIDUMP_H_
|
||||
#define CRASHPAD_SNAPSHOT_MINIDUMP_MODULE_SNAPSHOT_MINIDUMP_H_
|
||||
|
||||
#include <windows.h>
|
||||
#include <dbghelp.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "snapshot/module_snapshot.h"
|
||||
#include "util/file/file_reader.h"
|
||||
#include "util/misc/initialization_state_dcheck.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace internal {
|
||||
|
||||
//! \brief A ModuleSnapshot based on a module in a minidump file.
|
||||
class ModuleSnapshotMinidump final : public ModuleSnapshot {
|
||||
public:
|
||||
ModuleSnapshotMinidump();
|
||||
~ModuleSnapshotMinidump() override;
|
||||
|
||||
//! \brief Initializes the object.
|
||||
//!
|
||||
//! \param[in] file_reader A file reader corresponding to a minidump file.
|
||||
//! The file reader must support seeking.
|
||||
//! \param[in] minidump_module_rva The file offset in \a file_reader at which
|
||||
//! the module’s MINIDUMP_MODULE structure is located.
|
||||
//! \param[in] minidump_crashpad_module_info_location The location in \a
|
||||
//! file_reader at which the module’s corresponding
|
||||
//! MinidumpModuleCrashpadInfo structure is located. If no such
|
||||
//! corresponding structure is available for a module, this may be
|
||||
//! `nullptr`.
|
||||
//!
|
||||
//! \return `true` if the snapshot could be created, `false` otherwise with
|
||||
//! an appropriate message logged.
|
||||
bool Initialize(FileReaderInterface* file_reader,
|
||||
RVA minidump_module_rva,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR*
|
||||
minidump_crashpad_module_info_location);
|
||||
|
||||
// ModuleSnapshot:
|
||||
|
||||
std::string Name() const override;
|
||||
uint64_t Address() const override;
|
||||
uint64_t Size() const override;
|
||||
time_t Timestamp() const override;
|
||||
void FileVersion(uint16_t* version_0,
|
||||
uint16_t* version_1,
|
||||
uint16_t* version_2,
|
||||
uint16_t* version_3) const override;
|
||||
void SourceVersion(uint16_t* version_0,
|
||||
uint16_t* version_1,
|
||||
uint16_t* version_2,
|
||||
uint16_t* version_3) const override;
|
||||
ModuleType GetModuleType() const override;
|
||||
void UUID(crashpad::UUID* uuid) const override;
|
||||
std::vector<std::string> AnnotationsVector() const override;
|
||||
std::map<std::string, std::string> AnnotationsSimpleMap() const override;
|
||||
|
||||
private:
|
||||
// Initializes data carried in a MinidumpModuleCrashpadInfo structure on
|
||||
// behalf of Initialize().
|
||||
bool InitializeModuleCrashpadInfo(FileReaderInterface* file_reader,
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR*
|
||||
minidump_module_crashpad_info_location);
|
||||
|
||||
MINIDUMP_MODULE minidump_module_;
|
||||
std::vector<std::string> annotations_vector_;
|
||||
std::map<std::string, std::string> annotations_simple_map_;
|
||||
InitializationStateDcheck initialized_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ModuleSnapshotMinidump);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace crashpad
|
||||
|
||||
#endif // CRASHPAD_SNAPSHOT_MINIDUMP_MODULE_SNAPSHOT_MINIDUMP_H_
|
@ -14,6 +14,9 @@
|
||||
|
||||
#include "snapshot/minidump/process_snapshot_minidump.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "util/file/file_io.h"
|
||||
#include "snapshot/minidump/minidump_simple_string_dictionary_reader.h"
|
||||
|
||||
@ -24,6 +27,7 @@ ProcessSnapshotMinidump::ProcessSnapshotMinidump()
|
||||
header_(),
|
||||
stream_directory_(),
|
||||
stream_map_(),
|
||||
modules_(),
|
||||
crashpad_info_(),
|
||||
annotations_simple_map_(),
|
||||
file_reader_(nullptr),
|
||||
@ -80,33 +84,35 @@ bool ProcessSnapshotMinidump::Initialize(FileReaderInterface* file_reader) {
|
||||
|
||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||
|
||||
InitializeCrashpadInfo();
|
||||
if (!InitializeCrashpadInfo()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return InitializeModules();
|
||||
}
|
||||
|
||||
pid_t ProcessSnapshotMinidump::ProcessID() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED();
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
return 0;
|
||||
}
|
||||
|
||||
pid_t ProcessSnapshotMinidump::ParentProcessID() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED();
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ProcessSnapshotMinidump::SnapshotTime(timeval* snapshot_time) const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED();
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
snapshot_time->tv_sec = 0;
|
||||
snapshot_time->tv_usec = 0;
|
||||
}
|
||||
|
||||
void ProcessSnapshotMinidump::ProcessStartTime(timeval* start_time) const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED();
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
start_time->tv_sec = 0;
|
||||
start_time->tv_usec = 0;
|
||||
}
|
||||
@ -114,7 +120,7 @@ void ProcessSnapshotMinidump::ProcessStartTime(timeval* start_time) const {
|
||||
void ProcessSnapshotMinidump::ProcessCPUTimes(timeval* user_time,
|
||||
timeval* system_time) const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED();
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
user_time->tv_sec = 0;
|
||||
user_time->tv_usec = 0;
|
||||
system_time->tv_sec = 0;
|
||||
@ -128,62 +134,185 @@ ProcessSnapshotMinidump::AnnotationsSimpleMap() const {
|
||||
// annotations_simple_map_ to be lazily constructed: InitializeCrashpadInfo()
|
||||
// could be called here, and from other locations that require it, rather than
|
||||
// calling it from Initialize().
|
||||
// https://code.google.com/p/crashpad/issues/detail?id=9
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
return annotations_simple_map_;
|
||||
}
|
||||
|
||||
const SystemSnapshot* ProcessSnapshotMinidump::System() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED();
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<const ThreadSnapshot*> ProcessSnapshotMinidump::Threads() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED();
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
return std::vector<const ThreadSnapshot*>();
|
||||
}
|
||||
|
||||
std::vector<const ModuleSnapshot*> ProcessSnapshotMinidump::Modules() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED();
|
||||
return std::vector<const ModuleSnapshot*>();
|
||||
std::vector<const ModuleSnapshot*> modules;
|
||||
for (internal::ModuleSnapshotMinidump* module : modules_) {
|
||||
modules.push_back(module);
|
||||
}
|
||||
return modules;
|
||||
}
|
||||
|
||||
const ExceptionSnapshot* ProcessSnapshotMinidump::Exception() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
NOTREACHED();
|
||||
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ProcessSnapshotMinidump::InitializeCrashpadInfo() {
|
||||
const auto& it = stream_map_.find(kMinidumpStreamTypeCrashpadInfo);
|
||||
if (it == stream_map_.end()) {
|
||||
return;
|
||||
bool ProcessSnapshotMinidump::InitializeCrashpadInfo() {
|
||||
const auto& stream_it = stream_map_.find(kMinidumpStreamTypeCrashpadInfo);
|
||||
if (stream_it == stream_map_.end()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (it->second->DataSize < sizeof(crashpad_info_)) {
|
||||
if (stream_it->second->DataSize < sizeof(crashpad_info_)) {
|
||||
LOG(ERROR) << "crashpad_info size mismatch";
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_reader_->SeekSet(it->second->Rva)) {
|
||||
return;
|
||||
if (!file_reader_->SeekSet(stream_it->second->Rva)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_reader_->ReadExactly(&crashpad_info_, sizeof(crashpad_info_))) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (crashpad_info_.version != MinidumpCrashpadInfo::kVersion) {
|
||||
LOG(ERROR) << "crashpad_info version mismatch";
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal::ReadMinidumpSimpleStringDictionary(
|
||||
return internal::ReadMinidumpSimpleStringDictionary(
|
||||
file_reader_,
|
||||
crashpad_info_.simple_annotations,
|
||||
&annotations_simple_map_);
|
||||
}
|
||||
|
||||
bool ProcessSnapshotMinidump::InitializeModules() {
|
||||
const auto& stream_it = stream_map_.find(kMinidumpStreamTypeModuleList);
|
||||
if (stream_it == stream_map_.end()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::map<uint32_t, MINIDUMP_LOCATION_DESCRIPTOR> module_crashpad_info_links;
|
||||
if (!InitializeModulesCrashpadInfo(&module_crashpad_info_links)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stream_it->second->DataSize < sizeof(MINIDUMP_MODULE_LIST)) {
|
||||
LOG(ERROR) << "module_list size mismatch";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_reader_->SeekSet(stream_it->second->Rva)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t module_count;
|
||||
if (!file_reader_->ReadExactly(&module_count, sizeof(module_count))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sizeof(MINIDUMP_MODULE_LIST) + module_count * sizeof(MINIDUMP_MODULE) !=
|
||||
stream_it->second->DataSize) {
|
||||
LOG(ERROR) << "module_list size mismatch";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t module_index = 0; module_index < module_count; ++module_index) {
|
||||
const RVA module_rva = stream_it->second->Rva + sizeof(module_count) +
|
||||
module_index * sizeof(MINIDUMP_MODULE);
|
||||
|
||||
const auto& module_crashpad_info_it =
|
||||
module_crashpad_info_links.find(module_index);
|
||||
const MINIDUMP_LOCATION_DESCRIPTOR* module_crashpad_info_location =
|
||||
module_crashpad_info_it != module_crashpad_info_links.end()
|
||||
? &module_crashpad_info_it->second
|
||||
: nullptr;
|
||||
|
||||
auto module = make_scoped_ptr(new internal::ModuleSnapshotMinidump());
|
||||
if (!module->Initialize(
|
||||
file_reader_, module_rva, module_crashpad_info_location)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
modules_.push_back(module.release());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProcessSnapshotMinidump::InitializeModulesCrashpadInfo(
|
||||
std::map<uint32_t, MINIDUMP_LOCATION_DESCRIPTOR>*
|
||||
module_crashpad_info_links) {
|
||||
module_crashpad_info_links->clear();
|
||||
|
||||
if (crashpad_info_.version != MinidumpCrashpadInfo::kVersion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (crashpad_info_.module_list.Rva == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (crashpad_info_.module_list.DataSize <
|
||||
sizeof(MinidumpModuleCrashpadInfoList)) {
|
||||
LOG(ERROR) << "module_crashpad_info_list size mismatch";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!file_reader_->SeekSet(crashpad_info_.module_list.Rva)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t crashpad_module_count;
|
||||
if (!file_reader_->ReadExactly(&crashpad_module_count,
|
||||
sizeof(crashpad_module_count))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (crashpad_info_.module_list.DataSize !=
|
||||
sizeof(MinidumpModuleCrashpadInfoList) +
|
||||
crashpad_module_count * sizeof(MinidumpModuleCrashpadInfoLink)) {
|
||||
LOG(ERROR) << "module_crashpad_info_list size mismatch";
|
||||
return false;
|
||||
}
|
||||
|
||||
scoped_ptr<MinidumpModuleCrashpadInfoLink[]> minidump_links(
|
||||
new MinidumpModuleCrashpadInfoLink[crashpad_module_count]);
|
||||
if (!file_reader_->ReadExactly(
|
||||
&minidump_links[0],
|
||||
crashpad_module_count * sizeof(MinidumpModuleCrashpadInfoLink))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t crashpad_module_index = 0;
|
||||
crashpad_module_index < crashpad_module_count;
|
||||
++crashpad_module_index) {
|
||||
const MinidumpModuleCrashpadInfoLink& minidump_link =
|
||||
minidump_links[crashpad_module_index];
|
||||
if (module_crashpad_info_links->find(
|
||||
minidump_link.minidump_module_list_index) !=
|
||||
module_crashpad_info_links->end()) {
|
||||
LOG(WARNING)
|
||||
<< "duplicate module_crashpad_info_list minidump_module_list_index "
|
||||
<< minidump_link.minidump_module_list_index;
|
||||
return false;
|
||||
} else {
|
||||
module_crashpad_info_links->insert(std::make_pair(
|
||||
minidump_link.minidump_module_list_index, minidump_link.location));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
||||
|
@ -26,12 +26,14 @@
|
||||
#include "base/basictypes.h"
|
||||
#include "minidump/minidump_extensions.h"
|
||||
#include "snapshot/exception_snapshot.h"
|
||||
#include "snapshot/minidump/module_snapshot_minidump.h"
|
||||
#include "snapshot/module_snapshot.h"
|
||||
#include "snapshot/process_snapshot.h"
|
||||
#include "snapshot/system_snapshot.h"
|
||||
#include "snapshot/thread_snapshot.h"
|
||||
#include "util/file/file_reader.h"
|
||||
#include "util/misc/initialization_state_dcheck.h"
|
||||
#include "util/stdlib/pointer_container.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
@ -67,11 +69,23 @@ class ProcessSnapshotMinidump final : public ProcessSnapshot {
|
||||
private:
|
||||
// Initializes data carried in a MinidumpCrashpadInfo stream on behalf of
|
||||
// Initialize().
|
||||
void InitializeCrashpadInfo();
|
||||
bool InitializeCrashpadInfo();
|
||||
|
||||
// Initializes data carried in a MINIDUMP_MODULE_LIST stream on behalf of
|
||||
// Initialize().
|
||||
bool InitializeModules();
|
||||
|
||||
// Initializes data carried in a MinidumpModuleCrashpadInfoList structure on
|
||||
// behalf of InitializeModules(). This makes use of MinidumpCrashpadInfo as
|
||||
// well, so it must be called after InitializeCrashpadInfo().
|
||||
bool InitializeModulesCrashpadInfo(
|
||||
std::map<uint32_t, MINIDUMP_LOCATION_DESCRIPTOR>*
|
||||
module_crashpad_info_links);
|
||||
|
||||
MINIDUMP_HEADER header_;
|
||||
std::vector<MINIDUMP_DIRECTORY> stream_directory_;
|
||||
std::map<MinidumpStreamType, const MINIDUMP_LOCATION_DESCRIPTOR*> stream_map_;
|
||||
PointerVector<internal::ModuleSnapshotMinidump> modules_;
|
||||
MinidumpCrashpadInfo crashpad_info_;
|
||||
std::map<std::string, std::string> annotations_simple_map_;
|
||||
FileReaderInterface* file_reader_; // weak
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "snapshot/module_snapshot.h"
|
||||
#include "util/file/string_file.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -57,51 +58,84 @@ TEST(ProcessSnapshotMinidump, Empty) {
|
||||
EXPECT_TRUE(process_snapshot.Initialize(&string_file));
|
||||
}
|
||||
|
||||
// Writes |string| to |writer| as a MinidumpUTF8String, and returns the file
|
||||
// offst of the beginning of the string.
|
||||
RVA WriteString(FileWriterInterface* writer, const std::string& string) {
|
||||
RVA rva = static_cast<RVA>(writer->SeekGet());
|
||||
|
||||
uint32_t string_size = string.size();
|
||||
EXPECT_TRUE(writer->Write(&string_size, sizeof(string_size)));
|
||||
|
||||
// Include the trailing NUL character.
|
||||
EXPECT_TRUE(writer->Write(string.c_str(), string.size() + 1));
|
||||
|
||||
return rva;
|
||||
}
|
||||
|
||||
// Writes |dictionary| to |writer| as a MinidumpSimpleStringDictionary, and
|
||||
// populates |location| with a location descriptor identifying what was written.
|
||||
void WriteMinidumpSimpleStringDictionary(
|
||||
MINIDUMP_LOCATION_DESCRIPTOR* location,
|
||||
FileWriterInterface* writer,
|
||||
const std::map<std::string, std::string>& dictionary) {
|
||||
std::vector<MinidumpSimpleStringDictionaryEntry> entries;
|
||||
for (const auto& it : dictionary) {
|
||||
MinidumpSimpleStringDictionaryEntry entry;
|
||||
entry.key = WriteString(writer, it.first);
|
||||
entry.value = WriteString(writer, it.second);
|
||||
entries.push_back(entry);
|
||||
}
|
||||
|
||||
location->Rva = static_cast<RVA>(writer->SeekGet());
|
||||
|
||||
const uint32_t simple_string_dictionary_entries = entries.size();
|
||||
EXPECT_TRUE(writer->Write(&simple_string_dictionary_entries,
|
||||
sizeof(simple_string_dictionary_entries)));
|
||||
for (const MinidumpSimpleStringDictionaryEntry& entry : entries) {
|
||||
EXPECT_TRUE(writer->Write(&entry, sizeof(entry)));
|
||||
}
|
||||
|
||||
location->DataSize =
|
||||
sizeof(simple_string_dictionary_entries) +
|
||||
entries.size() * sizeof(MinidumpSimpleStringDictionaryEntry);
|
||||
}
|
||||
|
||||
// Writes |strings| to |writer| as a MinidumpRVAList referencing
|
||||
// MinidumpUTF8String objects, and populates |location| with a location
|
||||
// descriptor identifying what was written.
|
||||
void WriteMinidumpStringList(MINIDUMP_LOCATION_DESCRIPTOR* location,
|
||||
FileWriterInterface* writer,
|
||||
const std::vector<std::string>& strings) {
|
||||
std::vector<RVA> rvas;
|
||||
for (const std::string& string : strings) {
|
||||
rvas.push_back(WriteString(writer, string));
|
||||
}
|
||||
|
||||
location->Rva = static_cast<RVA>(writer->SeekGet());
|
||||
|
||||
const uint32_t string_list_entries = rvas.size();
|
||||
EXPECT_TRUE(writer->Write(&string_list_entries, sizeof(string_list_entries)));
|
||||
for (RVA rva : rvas) {
|
||||
EXPECT_TRUE(writer->Write(&rva, sizeof(rva)));
|
||||
}
|
||||
|
||||
location->DataSize = sizeof(string_list_entries) + rvas.size() * sizeof(RVA);
|
||||
}
|
||||
|
||||
TEST(ProcessSnapshotMinidump, AnnotationsSimpleMap) {
|
||||
StringFile string_file;
|
||||
|
||||
MINIDUMP_HEADER header = {};
|
||||
EXPECT_TRUE(string_file.Write(&header, sizeof(header)));
|
||||
|
||||
MinidumpSimpleStringDictionaryEntry entry0 = {};
|
||||
entry0.key = static_cast<RVA>(string_file.SeekGet());
|
||||
const char kKey0[] = "the first key";
|
||||
uint32_t string_size = strlen(kKey0);
|
||||
EXPECT_TRUE(string_file.Write(&string_size, sizeof(string_size)));
|
||||
EXPECT_TRUE(string_file.Write(kKey0, sizeof(kKey0)));
|
||||
|
||||
entry0.value = static_cast<RVA>(string_file.SeekGet());
|
||||
const char kValue0[] = "THE FIRST VALUE EVER!";
|
||||
string_size = strlen(kValue0);
|
||||
EXPECT_TRUE(string_file.Write(&string_size, sizeof(string_size)));
|
||||
EXPECT_TRUE(string_file.Write(kValue0, sizeof(kValue0)));
|
||||
|
||||
MinidumpSimpleStringDictionaryEntry entry1 = {};
|
||||
entry1.key = static_cast<RVA>(string_file.SeekGet());
|
||||
const char kKey1[] = "2key";
|
||||
string_size = strlen(kKey1);
|
||||
EXPECT_TRUE(string_file.Write(&string_size, sizeof(string_size)));
|
||||
EXPECT_TRUE(string_file.Write(kKey1, sizeof(kKey1)));
|
||||
|
||||
entry1.value = static_cast<RVA>(string_file.SeekGet());
|
||||
const char kValue1[] = "a lowly second value";
|
||||
string_size = strlen(kValue1);
|
||||
EXPECT_TRUE(string_file.Write(&string_size, sizeof(string_size)));
|
||||
EXPECT_TRUE(string_file.Write(kValue1, sizeof(kValue1)));
|
||||
|
||||
MinidumpCrashpadInfo crashpad_info = {};
|
||||
crashpad_info.version = MinidumpCrashpadInfo::kVersion;
|
||||
|
||||
crashpad_info.simple_annotations.Rva =
|
||||
static_cast<RVA>(string_file.SeekGet());
|
||||
uint32_t simple_string_dictionary_entries = 2;
|
||||
EXPECT_TRUE(string_file.Write(&simple_string_dictionary_entries,
|
||||
sizeof(simple_string_dictionary_entries)));
|
||||
EXPECT_TRUE(string_file.Write(&entry0, sizeof(entry0)));
|
||||
EXPECT_TRUE(string_file.Write(&entry1, sizeof(entry1)));
|
||||
crashpad_info.simple_annotations.DataSize =
|
||||
simple_string_dictionary_entries *
|
||||
sizeof(MinidumpSimpleStringDictionaryEntry);
|
||||
std::map<std::string, std::string> dictionary;
|
||||
dictionary["the first key"] = "THE FIRST VALUE EVER!";
|
||||
dictionary["2key"] = "a lowly second value";
|
||||
WriteMinidumpSimpleStringDictionary(
|
||||
&crashpad_info.simple_annotations, &string_file, dictionary);
|
||||
|
||||
MINIDUMP_DIRECTORY crashpad_info_directory = {};
|
||||
crashpad_info_directory.StreamType = kMinidumpStreamTypeCrashpadInfo;
|
||||
@ -124,15 +158,126 @@ TEST(ProcessSnapshotMinidump, AnnotationsSimpleMap) {
|
||||
EXPECT_TRUE(process_snapshot.Initialize(&string_file));
|
||||
|
||||
const auto annotations_simple_map = process_snapshot.AnnotationsSimpleMap();
|
||||
EXPECT_EQ(2u, annotations_simple_map.size());
|
||||
EXPECT_EQ(dictionary, annotations_simple_map);
|
||||
}
|
||||
|
||||
auto it = annotations_simple_map.find(kKey0);
|
||||
ASSERT_NE(it, annotations_simple_map.end());
|
||||
EXPECT_EQ(kValue0, it->second);
|
||||
TEST(ProcessSnapshotMinidump, Modules) {
|
||||
StringFile string_file;
|
||||
|
||||
it = annotations_simple_map.find(kKey1);
|
||||
ASSERT_NE(it, annotations_simple_map.end());
|
||||
EXPECT_EQ(kValue1, it->second);
|
||||
MINIDUMP_HEADER header = {};
|
||||
EXPECT_TRUE(string_file.Write(&header, sizeof(header)));
|
||||
|
||||
MINIDUMP_MODULE minidump_module = {};
|
||||
uint32_t minidump_module_count = 3;
|
||||
|
||||
MINIDUMP_DIRECTORY minidump_module_list_directory = {};
|
||||
minidump_module_list_directory.StreamType = kMinidumpStreamTypeModuleList;
|
||||
minidump_module_list_directory.Location.DataSize =
|
||||
sizeof(MINIDUMP_MODULE_LIST) +
|
||||
minidump_module_count * sizeof(MINIDUMP_MODULE);
|
||||
minidump_module_list_directory.Location.Rva =
|
||||
static_cast<RVA>(string_file.SeekGet());
|
||||
|
||||
EXPECT_TRUE(
|
||||
string_file.Write(&minidump_module_count, sizeof(minidump_module_count)));
|
||||
for (uint32_t minidump_module_index = 0;
|
||||
minidump_module_index < minidump_module_count;
|
||||
++minidump_module_index) {
|
||||
EXPECT_TRUE(string_file.Write(&minidump_module, sizeof(minidump_module)));
|
||||
}
|
||||
|
||||
MinidumpModuleCrashpadInfo crashpad_module_0 = {};
|
||||
crashpad_module_0.version = MinidumpModuleCrashpadInfo::kVersion;
|
||||
std::map<std::string, std::string> dictionary_0;
|
||||
dictionary_0["ptype"] = "browser";
|
||||
dictionary_0["pid"] = "12345";
|
||||
WriteMinidumpSimpleStringDictionary(
|
||||
&crashpad_module_0.simple_annotations, &string_file, dictionary_0);
|
||||
|
||||
MinidumpModuleCrashpadInfoLink crashpad_module_0_link = {};
|
||||
crashpad_module_0_link.minidump_module_list_index = 0;
|
||||
crashpad_module_0_link.location.DataSize = sizeof(crashpad_module_0);
|
||||
crashpad_module_0_link.location.Rva = static_cast<RVA>(string_file.SeekGet());
|
||||
EXPECT_TRUE(string_file.Write(&crashpad_module_0, sizeof(crashpad_module_0)));
|
||||
|
||||
MinidumpModuleCrashpadInfo crashpad_module_2 = {};
|
||||
crashpad_module_2.version = MinidumpModuleCrashpadInfo::kVersion;
|
||||
std::map<std::string, std::string> dictionary_2;
|
||||
dictionary_2["fakemodule"] = "yes";
|
||||
WriteMinidumpSimpleStringDictionary(
|
||||
&crashpad_module_2.simple_annotations, &string_file, dictionary_2);
|
||||
|
||||
std::vector<std::string> list_annotations_2;
|
||||
list_annotations_2.push_back("first string");
|
||||
list_annotations_2.push_back("last string");
|
||||
WriteMinidumpStringList(
|
||||
&crashpad_module_2.list_annotations, &string_file, list_annotations_2);
|
||||
|
||||
MinidumpModuleCrashpadInfoLink crashpad_module_2_link = {};
|
||||
crashpad_module_2_link.minidump_module_list_index = 2;
|
||||
crashpad_module_2_link.location.DataSize = sizeof(crashpad_module_2);
|
||||
crashpad_module_2_link.location.Rva = static_cast<RVA>(string_file.SeekGet());
|
||||
EXPECT_TRUE(string_file.Write(&crashpad_module_2, sizeof(crashpad_module_2)));
|
||||
|
||||
MinidumpCrashpadInfo crashpad_info = {};
|
||||
crashpad_info.version = MinidumpCrashpadInfo::kVersion;
|
||||
|
||||
uint32_t crashpad_module_count = 2;
|
||||
|
||||
crashpad_info.module_list.DataSize =
|
||||
sizeof(MinidumpModuleCrashpadInfoList) +
|
||||
crashpad_module_count * sizeof(MinidumpModuleCrashpadInfoLink);
|
||||
crashpad_info.module_list.Rva = static_cast<RVA>(string_file.SeekGet());
|
||||
|
||||
EXPECT_TRUE(
|
||||
string_file.Write(&crashpad_module_count, sizeof(crashpad_module_count)));
|
||||
EXPECT_TRUE(string_file.Write(&crashpad_module_0_link,
|
||||
sizeof(crashpad_module_0_link)));
|
||||
EXPECT_TRUE(string_file.Write(&crashpad_module_2_link,
|
||||
sizeof(crashpad_module_2_link)));
|
||||
|
||||
MINIDUMP_DIRECTORY crashpad_info_directory = {};
|
||||
crashpad_info_directory.StreamType = kMinidumpStreamTypeCrashpadInfo;
|
||||
crashpad_info_directory.Location.DataSize = sizeof(crashpad_info);
|
||||
crashpad_info_directory.Location.Rva =
|
||||
static_cast<RVA>(string_file.SeekGet());
|
||||
EXPECT_TRUE(string_file.Write(&crashpad_info, sizeof(crashpad_info)));
|
||||
|
||||
header.StreamDirectoryRva = static_cast<RVA>(string_file.SeekGet());
|
||||
EXPECT_TRUE(string_file.Write(&minidump_module_list_directory,
|
||||
sizeof(minidump_module_list_directory)));
|
||||
EXPECT_TRUE(string_file.Write(&crashpad_info_directory,
|
||||
sizeof(crashpad_info_directory)));
|
||||
|
||||
header.Signature = MINIDUMP_SIGNATURE;
|
||||
header.Version = MINIDUMP_VERSION;
|
||||
header.NumberOfStreams = 2;
|
||||
EXPECT_TRUE(string_file.SeekSet(0));
|
||||
EXPECT_TRUE(string_file.Write(&header, sizeof(header)));
|
||||
|
||||
ProcessSnapshotMinidump process_snapshot;
|
||||
EXPECT_TRUE(process_snapshot.Initialize(&string_file));
|
||||
|
||||
std::vector<const ModuleSnapshot*> modules = process_snapshot.Modules();
|
||||
ASSERT_EQ(minidump_module_count, modules.size());
|
||||
|
||||
auto annotations_simple_map = modules[0]->AnnotationsSimpleMap();
|
||||
EXPECT_EQ(dictionary_0, annotations_simple_map);
|
||||
|
||||
auto annotations_vector = modules[0]->AnnotationsVector();
|
||||
EXPECT_TRUE(annotations_vector.empty());
|
||||
|
||||
annotations_simple_map = modules[1]->AnnotationsSimpleMap();
|
||||
EXPECT_TRUE(annotations_simple_map.empty());
|
||||
|
||||
annotations_vector = modules[1]->AnnotationsVector();
|
||||
EXPECT_TRUE(annotations_vector.empty());
|
||||
|
||||
annotations_simple_map = modules[2]->AnnotationsSimpleMap();
|
||||
EXPECT_EQ(dictionary_2, annotations_simple_map);
|
||||
|
||||
annotations_vector = modules[2]->AnnotationsVector();
|
||||
EXPECT_EQ(list_annotations_2, annotations_vector);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -69,8 +69,12 @@
|
||||
'mac/thread_snapshot_mac.h',
|
||||
'minidump/minidump_simple_string_dictionary_reader.cc',
|
||||
'minidump/minidump_simple_string_dictionary_reader.h',
|
||||
'minidump/minidump_string_list_reader.cc',
|
||||
'minidump/minidump_string_list_reader.h',
|
||||
'minidump/minidump_string_reader.cc',
|
||||
'minidump/minidump_string_reader.h',
|
||||
'minidump/module_snapshot_minidump.cc',
|
||||
'minidump/module_snapshot_minidump.h',
|
||||
'minidump/process_snapshot_minidump.cc',
|
||||
'minidump/process_snapshot_minidump.h',
|
||||
'memory_snapshot.h',
|
||||
|
Loading…
x
Reference in New Issue
Block a user