Some plumbing for the beginning of getting handles into snapshot/minidump

Follows https://codereview.chromium.org/1400413002/.

R=mark@chromium.org
BUG=crashpad:21, crashpad:46, crashpad:52

Review URL: https://codereview.chromium.org/1407643004 .
This commit is contained in:
Scott Graham 2015-10-16 15:58:40 -07:00
parent 7de04b02f8
commit 4600643a78
13 changed files with 205 additions and 3 deletions

View File

@ -621,6 +621,71 @@ struct __attribute__((packed, aligned(4))) MINIDUMP_MEMORY_LIST {
MINIDUMP_MEMORY_DESCRIPTOR MemoryRanges[0];
};
//! \brief Contains the state of an individual system handle at the time the
//! snapshot was taken. This structure is Windows-specific.
//!
//! \sa MINIDUMP_HANDLE_DESCRIPTOR_2
struct __attribute__((packed, aligned(4))) MINIDUMP_HANDLE_DESCRIPTOR {
//! \brief The Windows `HANDLE` value.
uint64_t Handle;
//! \brief An RVA to a MINIDUMP_STRING structure that specifies the object
//! type of the handle. This member can be zero.
RVA TypeNameRva;
//! \brief An RVA to a MINIDUMP_STRING structure that specifies the object
//! name of the handle. This member can be zero.
RVA ObjectNameRva;
//! \brief The attributes for the handle, this corresponds to `OBJ_INHERIT`,
//! `OBJ_CASE_INSENSITIVE`, etc.
uint32_t Attributes;
//! \brief The `ACCESS_MASK` for the handle.
uint32_t GrantedAccess;
//! \brief This is the number of open handles to the object that this handle
//! refers to.
uint32_t HandleCount;
//! \brief This is the number kernel references to the object that this
//! handle refers to.
uint32_t PointerCount;
};
//! \brief Contains the state of an individual system handle at the time the
//! snapshot was taken. This structure is Windows-specific.
//!
//! \sa MINIDUMP_HANDLE_DESCRIPTOR
struct __attribute__((packed, aligned(4))) MINIDUMP_HANDLE_DESCRIPTOR_2
: public MINIDUMP_HANDLE_DESCRIPTOR {
//! \brief An RVA to a MINIDUMP_HANDLE_OBJECT_INFORMATION structure that
//! specifies object-specific information. This member can be zero if
//! there is no extra information.
RVA ObjectInfoRva;
//! \brief Must be zero.
uint32_t Reserved0;
};
//! \brief Represents the header for a handle data stream.
struct __attribute((packed, aligned(4))) MINIDUMP_HANDLE_DATA_STREAM {
//! \brief The size of the header information for the stream, in bytes. This
//! value is `sizeof(MINIDUMP_HANDLE_DATA_STREAM)`.
uint32_t SizeOfHeader;
//! \brief The size of a descriptor in the stream, in bytes. This value is
//! `sizeof(MINIDUMP_HANDLE_DESCRIPTOR)` or
//! `sizeof(MINIDUMP_HANDLE_DESCRIPTOR_2)`.
uint32_t SizeOfDescriptor;
//! \brief The number of descriptors in the stream.
uint32_t NumberOfDescriptors;
//! \brief Must be zero.
uint32_t Reserved;
};
//! \anchor MINIDUMP_MISCx
//! \name MINIDUMP_MISC*
//!

View File

@ -0,0 +1,31 @@
// 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/handle_snapshot.h"
namespace crashpad {
HandleSnapshot::HandleSnapshot()
: type_name(),
handle(0),
attributes(0),
granted_access(0),
pointer_count(0),
handle_count(0) {
}
HandleSnapshot::~HandleSnapshot() {
}
} // namespace crashpad

View File

@ -0,0 +1,56 @@
// 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_HANDLE_SNAPSHOT_H_
#define CRASHPAD_SNAPSHOT_HANDLE_SNAPSHOT_H_
#include <stdint.h>
#include <string>
namespace crashpad {
struct HandleSnapshot {
HandleSnapshot();
~HandleSnapshot();
//! \brief A string representation of the handle's type.
std::wstring type_name;
//! \brief The handle's value.
uint32_t handle;
//! \brief The attributes for the handle, e.g. `OBJ_INHERIT`,
//! `OBJ_CASE_INSENSITIVE`, etc.
uint32_t attributes;
//! \brief The ACCESS_MASK for the handle in this process.
//!
//! See
//! http://blogs.msdn.com/b/openspecification/archive/2010/04/01/about-the-access-mask-structure.aspx
//! for more information.
uint32_t granted_access;
//! \brief The number of kernel references to the object that this handle
//! refers to.
uint32_t pointer_count;
//! \brief The number of open handles to the object that this handle refers
//! to.
uint32_t handle_count;
};
} // namespace crashpad
#endif // CRASHPAD_SNAPSHOT_HANDLE_SNAPSHOT_H_

View File

@ -184,6 +184,12 @@ std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotMinidump::MemoryMap()
return std::vector<const MemoryMapRegionSnapshot*>();
}
std::vector<HandleSnapshot> ProcessSnapshotMinidump::Handles() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
NOTREACHED(); // https://code.google.com/p/crashpad/issues/detail?id=10
return std::vector<HandleSnapshot>();
}
std::vector<const MemorySnapshot*> ProcessSnapshotMinidump::ExtraMemory()
const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);

View File

@ -70,6 +70,7 @@ class ProcessSnapshotMinidump final : public ProcessSnapshot {
std::vector<const ModuleSnapshot*> Modules() const override;
const ExceptionSnapshot* Exception() const override;
std::vector<const MemoryMapRegionSnapshot*> MemoryMap() const override;
std::vector<HandleSnapshot> Handles() const override;
std::vector<const MemorySnapshot*> ExtraMemory() const override;
private:

View File

@ -22,6 +22,7 @@
#include <string>
#include <vector>
#include "snapshot/handle_snapshot.h"
#include "util/misc/uuid.h"
namespace crashpad {
@ -171,6 +172,12 @@ class ProcessSnapshot {
//! the ProcessSnapshot object that they were obtained from.
virtual std::vector<const MemoryMapRegionSnapshot*> MemoryMap() const = 0;
//! \brief Returns HandleSnapshot objects reflecting the open handles in the
//! snapshot process at the time of the snapshot.
//!
//! \return A vector of HandleSnapshot objects.
virtual std::vector<HandleSnapshot> Handles() const = 0;
//! \brief Returns a vector of additional memory blocks that should be
//! included in a minidump.
//!

View File

@ -36,6 +36,8 @@
'crashpad_info_client_options.cc',
'crashpad_info_client_options.h',
'exception_snapshot.h',
'handle_snapshot.cc',
'handle_snapshot.h',
'mac/cpu_context_mac.cc',
'mac/cpu_context_mac.h',
'mac/exception_snapshot_mac.cc',

View File

@ -34,6 +34,7 @@ TestProcessSnapshot::TestProcessSnapshot()
modules_(),
exception_(),
memory_map_(),
handles_(),
extra_memory_() {
}
@ -107,6 +108,10 @@ std::vector<const MemoryMapRegionSnapshot*> TestProcessSnapshot::MemoryMap()
return memory_map;
}
std::vector<HandleSnapshot> TestProcessSnapshot::Handles() const {
return handles_;
}
std::vector<const MemorySnapshot*> TestProcessSnapshot::ExtraMemory() const {
std::vector<const MemorySnapshot*> extra_memory;
for (const auto& em : extra_memory_)

View File

@ -106,6 +106,13 @@ class TestProcessSnapshot final : public ProcessSnapshot {
memory_map_.push_back(region.release());
}
//! \brief Adds a handle snapshot to be returned by Handles().
//!
//! \param[in] region The handle snapshot that will be included in Handles().
void AddHandle(const HandleSnapshot& handle) {
handles_.push_back(handle);
}
//! \brief Add a memory snapshot to be returned by ExtraMemory().
//!
//! \param[in] extra_memory The memory snapshot that will be included in
@ -131,6 +138,7 @@ class TestProcessSnapshot final : public ProcessSnapshot {
std::vector<const ModuleSnapshot*> Modules() const override;
const ExceptionSnapshot* Exception() const override;
std::vector<const MemoryMapRegionSnapshot*> MemoryMap() const override;
std::vector<HandleSnapshot> Handles() const override;
std::vector<const MemorySnapshot*> ExtraMemory() const override;
private:
@ -148,6 +156,7 @@ class TestProcessSnapshot final : public ProcessSnapshot {
PointerVector<ModuleSnapshot> modules_;
scoped_ptr<ExceptionSnapshot> exception_;
PointerVector<MemoryMapRegionSnapshot> memory_map_;
std::vector<HandleSnapshot> handles_;
PointerVector<MemorySnapshot> extra_memory_;
DISALLOW_COPY_AND_ASSIGN(TestProcessSnapshot);

View File

@ -207,6 +207,21 @@ std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotWin::MemoryMap()
return memory_map;
}
std::vector<HandleSnapshot> ProcessSnapshotWin::Handles() const {
std::vector<HandleSnapshot> result;
for (const auto& handle : process_reader_.GetProcessInfo().Handles()) {
HandleSnapshot snapshot;
snapshot.type_name = handle.type_name;
snapshot.handle = handle.handle;
snapshot.attributes = handle.attributes;
snapshot.granted_access = handle.granted_access;
snapshot.pointer_count = handle.pointer_count;
snapshot.handle_count = handle.handle_count;
result.push_back(snapshot);
}
return result;
}
std::vector<const MemorySnapshot*> ProcessSnapshotWin::ExtraMemory() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
std::vector<const MemorySnapshot*> extra_memory;

View File

@ -135,6 +135,7 @@ class ProcessSnapshotWin final : public ProcessSnapshot {
std::vector<const ModuleSnapshot*> Modules() const override;
const ExceptionSnapshot* Exception() const override;
std::vector<const MemoryMapRegionSnapshot*> MemoryMap() const override;
std::vector<HandleSnapshot> Handles() const override;
std::vector<const MemorySnapshot*> ExtraMemory() const override;
private:

View File

@ -602,7 +602,7 @@ ProcessInfo::GetReadableRanges(
return GetReadableRangesOfMemoryMap(range, MemoryInfo());
}
const std::vector<ProcessInfo::Handle>& ProcessInfo::Handles() {
const std::vector<ProcessInfo::Handle>& ProcessInfo::Handles() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
if (handles_.empty())
handles_ = BuildHandleVector(process_);

View File

@ -140,7 +140,7 @@ class ProcessInfo {
const CheckedRange<WinVMAddress, WinVMSize>& range) const;
//! \brief Retrieves information about open handles in the target process.
const std::vector<Handle>& Handles();
const std::vector<Handle>& Handles() const;
private:
template <class Traits>
@ -168,7 +168,11 @@ class ProcessInfo {
WinVMSize peb_size_;
std::vector<Module> modules_;
std::vector<MEMORY_BASIC_INFORMATION64> memory_info_;
std::vector<Handle> handles_;
// Handles() is logically const, but updates this member on first retrieval.
// See https://code.google.com/p/crashpad/issues/detail?id=9.
mutable std::vector<Handle> handles_;
bool is_64_bit_;
bool is_wow64_;
InitializationStateDcheck initialized_;