2022-09-06 19:14:07 -04:00
|
|
|
|
// Copyright 2014 The Crashpad Authors
|
2014-08-11 11:42:12 -07:00
|
|
|
|
//
|
|
|
|
|
// 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 "minidump/minidump_misc_info_writer.h"
|
|
|
|
|
|
2022-02-28 20:57:19 -08:00
|
|
|
|
#include <iterator>
|
2014-11-05 18:15:19 -05:00
|
|
|
|
#include <limits>
|
|
|
|
|
|
2020-09-01 17:09:37 -04:00
|
|
|
|
#include "base/check_op.h"
|
2014-08-11 11:42:12 -07:00
|
|
|
|
#include "base/logging.h"
|
|
|
|
|
#include "base/numerics/safe_conversions.h"
|
2014-11-05 18:15:19 -05:00
|
|
|
|
#include "base/strings/stringprintf.h"
|
2014-08-11 11:42:12 -07:00
|
|
|
|
#include "base/strings/utf_string_conversions.h"
|
2014-11-05 18:15:19 -05:00
|
|
|
|
#include "build/build_config.h"
|
2022-05-14 22:40:24 -07:00
|
|
|
|
#include "minidump/minidump_context_writer.h"
|
2014-08-11 11:42:12 -07:00
|
|
|
|
#include "minidump/minidump_writer_util.h"
|
2014-11-05 18:15:19 -05:00
|
|
|
|
#include "package.h"
|
2022-05-14 22:40:24 -07:00
|
|
|
|
#include "snapshot/cpu_context.h"
|
2014-11-05 18:15:19 -05:00
|
|
|
|
#include "snapshot/process_snapshot.h"
|
|
|
|
|
#include "snapshot/system_snapshot.h"
|
2022-05-14 22:40:24 -07:00
|
|
|
|
#include "snapshot/thread_snapshot.h"
|
2014-10-23 18:47:27 -04:00
|
|
|
|
#include "util/file/file_writer.h"
|
2014-11-05 18:15:19 -05:00
|
|
|
|
#include "util/numeric/in_range_cast.h"
|
2014-08-11 11:42:12 -07:00
|
|
|
|
#include "util/numeric/safe_assignment.h"
|
|
|
|
|
|
2022-01-19 15:00:24 -05:00
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
mac: Switch from <AvailabilityMacros.h> to <Availability.h>
The macOS 11.0 SDK, as of Xcode 12b6 12A8189n, has not updated
<AvailabilityMacros.h> with a MAC_OS_X_VERSION_11_0 or
MAC_OS_X_VERSION_10_16 constant. However, the <Availability.h> interface
has been updated to provide both __MAC_11_0 and __MAC_10_16.
<AvailabilityMacros.h>’s MAC_OS_X_VERSION_MAX_ALLOWED, which is supposed
to identify the SDK version, is broken in the 11.0 SDK in that whenever
the deployment target is set to 10.15 or earlier, the SDK will be
mis-identified through this interface as 10.15. When using the
<Availability.h> equivalent, __MAC_OS_X_VERSION_MAX_ALLOWED, the 11.0
SDK is identified as 10.16 (arguably it should be internally versioned
as 11.0, but at least this interface allows it to be detected
unambiguously.) It’s clear that the <AvailabilityMacros.h> interface
provides no meaningful support for the macOS 11.0 SDK at all, but
<Availability.h> does.
<Availability.h> was introduced in the Mac OS X 10.5 SDK, so there is no
relevant SDK version compatibility problem with this interface.
Key differences between these interfaces for the purposes used by
Crashpad:
- <AvailabilityMacros.h> → <Availability.h>
- MAC_OS_X_VERSION_MIN_REQUIRED (DT) → __MAC_OS_X_VERSION_MIN_REQUIRED
- MAC_OS_X_VERSION_MAX_ALLOWED (SDK) → __MAC_OS_X_VERSION_MAX_ALLOWED
- MAC_OS_X_VERSION_x_y → __MAC_x_y
- <Availability.h> __MAC_OS_X_VERSION_* SDK/DT macros are only
available when targeting macOS, while <AvailabilityMacros.h>
MAC_OS_X_VERSION_* SDK/DT macros are available on all Apple platforms,
which may be a source of confusion. (<Availability.h> __MAC_* macros
do remain available on all Apple platforms.)
This change was made mostly mechanically by:
sed -i '' -Ee 's/<AvailabilityMacros.h>/<Availability.h>/g' \
$(git grep -E -l '<AvailabilityMacros.h>' |
grep -v AvailabilityMacros.h)
sed -i '' -Ee 's/(MAC_OS_X_VERSION_(MIN_REQUIRED|MAX_ALLOWED))/__\1/g' \
$(git grep -E -l 'MAC_OS_X_VERSION_(MIN_REQUIRED|MAX_ALLOWED)' |
grep -v AvailabilityMacros.h)
sed -i '' -Ee 's/(MAC_OS_X_VERSION_(10_[0-9]+))/__MAC_\2/g' \
$(git grep -E -l 'MAC_OS_X_VERSION_(10_[0-9]+)' |
grep -v AvailabilityMacros.h)
Bug: crashpad:347
Change-Id: Ibdcd7a6215a82f7060b7b67d98691f88454085fc
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2382421
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Commit-Queue: Mark Mentovai <mark@chromium.org>
2020-08-28 20:00:15 -04:00
|
|
|
|
#include <Availability.h>
|
2022-01-19 15:00:24 -05:00
|
|
|
|
#elif BUILDFLAG(IS_ANDROID)
|
2016-11-01 15:59:40 -04:00
|
|
|
|
#include <android/api-level.h>
|
2014-11-05 18:15:19 -05:00
|
|
|
|
#endif
|
|
|
|
|
|
2014-08-11 11:42:12 -07:00
|
|
|
|
namespace crashpad {
|
2014-11-05 18:15:19 -05:00
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
uint32_t TimevalToRoundedSeconds(const timeval& tv) {
|
|
|
|
|
uint32_t seconds =
|
|
|
|
|
InRangeCast<uint32_t>(tv.tv_sec, std::numeric_limits<uint32_t>::max());
|
2017-07-25 19:15:48 -04:00
|
|
|
|
constexpr int kMicrosecondsPerSecond = static_cast<int>(1E6);
|
2014-11-05 18:15:19 -05:00
|
|
|
|
if (tv.tv_usec >= kMicrosecondsPerSecond / 2 &&
|
|
|
|
|
seconds != std::numeric_limits<uint32_t>::max()) {
|
|
|
|
|
++seconds;
|
|
|
|
|
}
|
|
|
|
|
return seconds;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For MINIDUMP_MISC_INFO_4::BuildString. dbghelp only places OS version
|
|
|
|
|
// information here, but if a machine description is also available, this is the
|
|
|
|
|
// only reasonable place in a minidump file to put it.
|
|
|
|
|
std::string BuildString(const SystemSnapshot* system_snapshot) {
|
|
|
|
|
std::string os_version_full = system_snapshot->OSVersionFull();
|
|
|
|
|
std::string machine_description = system_snapshot->MachineDescription();
|
|
|
|
|
if (!os_version_full.empty()) {
|
|
|
|
|
if (!machine_description.empty()) {
|
|
|
|
|
return base::StringPrintf(
|
|
|
|
|
"%s; %s", os_version_full.c_str(), machine_description.c_str());
|
|
|
|
|
}
|
|
|
|
|
return os_version_full;
|
|
|
|
|
}
|
|
|
|
|
return machine_description;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-19 15:00:24 -05:00
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
mac: Switch from <AvailabilityMacros.h> to <Availability.h>
The macOS 11.0 SDK, as of Xcode 12b6 12A8189n, has not updated
<AvailabilityMacros.h> with a MAC_OS_X_VERSION_11_0 or
MAC_OS_X_VERSION_10_16 constant. However, the <Availability.h> interface
has been updated to provide both __MAC_11_0 and __MAC_10_16.
<AvailabilityMacros.h>’s MAC_OS_X_VERSION_MAX_ALLOWED, which is supposed
to identify the SDK version, is broken in the 11.0 SDK in that whenever
the deployment target is set to 10.15 or earlier, the SDK will be
mis-identified through this interface as 10.15. When using the
<Availability.h> equivalent, __MAC_OS_X_VERSION_MAX_ALLOWED, the 11.0
SDK is identified as 10.16 (arguably it should be internally versioned
as 11.0, but at least this interface allows it to be detected
unambiguously.) It’s clear that the <AvailabilityMacros.h> interface
provides no meaningful support for the macOS 11.0 SDK at all, but
<Availability.h> does.
<Availability.h> was introduced in the Mac OS X 10.5 SDK, so there is no
relevant SDK version compatibility problem with this interface.
Key differences between these interfaces for the purposes used by
Crashpad:
- <AvailabilityMacros.h> → <Availability.h>
- MAC_OS_X_VERSION_MIN_REQUIRED (DT) → __MAC_OS_X_VERSION_MIN_REQUIRED
- MAC_OS_X_VERSION_MAX_ALLOWED (SDK) → __MAC_OS_X_VERSION_MAX_ALLOWED
- MAC_OS_X_VERSION_x_y → __MAC_x_y
- <Availability.h> __MAC_OS_X_VERSION_* SDK/DT macros are only
available when targeting macOS, while <AvailabilityMacros.h>
MAC_OS_X_VERSION_* SDK/DT macros are available on all Apple platforms,
which may be a source of confusion. (<Availability.h> __MAC_* macros
do remain available on all Apple platforms.)
This change was made mostly mechanically by:
sed -i '' -Ee 's/<AvailabilityMacros.h>/<Availability.h>/g' \
$(git grep -E -l '<AvailabilityMacros.h>' |
grep -v AvailabilityMacros.h)
sed -i '' -Ee 's/(MAC_OS_X_VERSION_(MIN_REQUIRED|MAX_ALLOWED))/__\1/g' \
$(git grep -E -l 'MAC_OS_X_VERSION_(MIN_REQUIRED|MAX_ALLOWED)' |
grep -v AvailabilityMacros.h)
sed -i '' -Ee 's/(MAC_OS_X_VERSION_(10_[0-9]+))/__MAC_\2/g' \
$(git grep -E -l 'MAC_OS_X_VERSION_(10_[0-9]+)' |
grep -v AvailabilityMacros.h)
Bug: crashpad:347
Change-Id: Ibdcd7a6215a82f7060b7b67d98691f88454085fc
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2382421
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Commit-Queue: Mark Mentovai <mark@chromium.org>
2020-08-28 20:00:15 -04:00
|
|
|
|
// Converts the value of the __MAC_OS_X_VERSION_MIN_REQUIRED or
|
|
|
|
|
// __MAC_OS_X_VERSION_MAX_ALLOWED macro from <Availability.h> to a number
|
2020-09-01 17:09:37 -04:00
|
|
|
|
// identifying the macOS version that it represents, in the same format used by
|
|
|
|
|
// MacOSVersionNumber(). For example, with an argument of __MAC_10_15, this
|
|
|
|
|
// function will return 10'15'00, which is incidentally the same as __MAC_10_15.
|
|
|
|
|
// With an argument of __MAC_10_9, this function will return 10'09'00, different
|
|
|
|
|
// from __MAC_10_9, which is 10'9'0.
|
|
|
|
|
int AvailabilityVersionToMacOSVersionNumber(int availability) {
|
|
|
|
|
#if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_10
|
|
|
|
|
DCHECK_GE(availability, 10'0'0);
|
|
|
|
|
|
|
|
|
|
// Until __MAC_10_10, the format is major * 1'0'0 + minor * 1'0 + bugfix.
|
|
|
|
|
if (availability >= 10'0'0 && availability <= 10'9'9) {
|
|
|
|
|
int minor = (availability / 1'0) % 1'0;
|
|
|
|
|
int bugfix = availability % 1'0;
|
|
|
|
|
return 10'00'00 + minor * 1'00 + bugfix;
|
2014-11-05 18:15:19 -05:00
|
|
|
|
}
|
2020-09-01 17:09:37 -04:00
|
|
|
|
#endif
|
2014-11-05 18:15:19 -05:00
|
|
|
|
|
2020-09-01 17:09:37 -04:00
|
|
|
|
// Since __MAC_10_10, the format is major * 1'00'00 + minor * 1'00 + bugfix.
|
|
|
|
|
DCHECK_GE(availability, 10'10'00);
|
|
|
|
|
DCHECK_LE(availability, 99'99'99);
|
2014-11-05 18:15:19 -05:00
|
|
|
|
|
2020-09-01 17:09:37 -04:00
|
|
|
|
return availability;
|
2014-11-05 18:15:19 -05:00
|
|
|
|
}
|
2022-01-19 15:00:24 -05:00
|
|
|
|
#endif // BUILDFLAG(IS_MAC)
|
2014-11-05 18:15:19 -05:00
|
|
|
|
|
2022-05-14 22:40:24 -07:00
|
|
|
|
bool MaybeSetXStateData(const ProcessSnapshot* process_snapshot,
|
|
|
|
|
XSTATE_CONFIG_FEATURE_MSC_INFO* xstate) {
|
|
|
|
|
// Cannot set xstate data if there are no threads.
|
|
|
|
|
auto threads = process_snapshot->Threads();
|
|
|
|
|
if (threads.size() == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// All threads should be the same as we request contexts in the same way.
|
|
|
|
|
auto context = threads.at(0)->Context();
|
|
|
|
|
|
|
|
|
|
// Only support AMD64.
|
|
|
|
|
if (context->architecture != kCPUArchitectureX86_64)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// If no extended features, then we will just write the standard context.
|
|
|
|
|
if (context->x86_64->xstate.enabled_features == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
xstate->SizeOfInfo = sizeof(*xstate);
|
|
|
|
|
// Needs to match the size of the context we'll write or the dump is invalid,
|
|
|
|
|
// so ask the first thread how large it will be.
|
|
|
|
|
auto context_writer = MinidumpContextWriter::CreateFromSnapshot(context);
|
|
|
|
|
xstate->ContextSize =
|
|
|
|
|
static_cast<uint32_t>(context_writer->FreezeAndGetSizeOfObject());
|
|
|
|
|
// Note: This isn't the same as xstateenabledfeatures!
|
|
|
|
|
xstate->EnabledFeatures =
|
|
|
|
|
context->x86_64->xstate.enabled_features | XSTATE_COMPACTION_ENABLE_MASK;
|
|
|
|
|
|
|
|
|
|
// Note: if other XSAVE entries are to be supported they will be in order,
|
|
|
|
|
// and may have different offsets depending on what is saved.
|
|
|
|
|
if (context->x86_64->xstate.enabled_features & XSTATE_MASK_CET_U) {
|
|
|
|
|
xstate->Features[XSTATE_CET_U].Offset = kXSaveAreaFirstOffset;
|
|
|
|
|
xstate->Features[XSTATE_CET_U].Size = sizeof(MinidumpAMD64XSaveFormatCetU);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-05 18:15:19 -05:00
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
|
|
// For MINIDUMP_MISC_INFO_4::DbgBldStr. dbghelp produces strings like
|
|
|
|
|
// “dbghelp.i386,6.3.9600.16520” and “dbghelp.amd64,6.3.9600.16520”. Mimic that
|
|
|
|
|
// format, and add the OS that wrote the minidump along with any relevant
|
|
|
|
|
// platform-specific data describing the compilation environment.
|
|
|
|
|
std::string MinidumpMiscInfoDebugBuildString() {
|
|
|
|
|
// Caution: the minidump file format only has room for 39 UTF-16 code units
|
|
|
|
|
// plus a UTF-16 NUL terminator. Don’t let strings get longer than this, or
|
|
|
|
|
// they will be truncated and a message will be logged.
|
2022-01-19 15:00:24 -05:00
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
2017-07-25 13:34:04 -04:00
|
|
|
|
static constexpr char kOS[] = "mac";
|
2022-01-19 15:00:24 -05:00
|
|
|
|
#elif BUILDFLAG(IS_IOS)
|
2020-09-01 17:09:37 -04:00
|
|
|
|
static constexpr char kOS[] = "ios";
|
2022-01-19 15:00:24 -05:00
|
|
|
|
#elif BUILDFLAG(IS_ANDROID)
|
2017-07-25 13:34:04 -04:00
|
|
|
|
static constexpr char kOS[] = "android";
|
2022-01-19 15:00:24 -05:00
|
|
|
|
#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
2017-07-25 13:34:04 -04:00
|
|
|
|
static constexpr char kOS[] = "linux";
|
2022-01-19 15:00:24 -05:00
|
|
|
|
#elif BUILDFLAG(IS_WIN)
|
2017-07-25 13:34:04 -04:00
|
|
|
|
static constexpr char kOS[] = "win";
|
2022-01-19 15:00:24 -05:00
|
|
|
|
#elif BUILDFLAG(IS_FUCHSIA)
|
2017-11-22 16:30:50 -08:00
|
|
|
|
static constexpr char kOS[] = "fuchsia";
|
2014-11-05 18:15:19 -05:00
|
|
|
|
#else
|
|
|
|
|
#error define kOS for this operating system
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(ARCH_CPU_X86)
|
2017-07-25 13:34:04 -04:00
|
|
|
|
static constexpr char kCPU[] = "i386";
|
2014-11-05 18:15:19 -05:00
|
|
|
|
#elif defined(ARCH_CPU_X86_64)
|
2017-07-25 13:34:04 -04:00
|
|
|
|
static constexpr char kCPU[] = "amd64";
|
2016-11-01 16:35:06 -04:00
|
|
|
|
#elif defined(ARCH_CPU_ARMEL)
|
2017-07-25 13:34:04 -04:00
|
|
|
|
static constexpr char kCPU[] = "arm";
|
2016-11-01 15:59:40 -04:00
|
|
|
|
#elif defined(ARCH_CPU_ARM64)
|
2017-07-25 13:34:04 -04:00
|
|
|
|
static constexpr char kCPU[] = "arm64";
|
2018-07-10 11:17:22 +02:00
|
|
|
|
#elif defined(ARCH_CPU_MIPSEL)
|
|
|
|
|
static constexpr char kCPU[] = "mips";
|
|
|
|
|
#elif defined(ARCH_CPU_MIPS64EL)
|
|
|
|
|
static constexpr char kCPU[] = "mips64";
|
2023-06-08 21:08:54 +00:00
|
|
|
|
#elif defined(ARCH_CPU_RISCV64)
|
|
|
|
|
static constexpr char kCPU[] = "riscv64";
|
2014-11-05 18:15:19 -05:00
|
|
|
|
#else
|
|
|
|
|
#error define kCPU for this CPU
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
std::string debug_build_string = base::StringPrintf("%s.%s,%s,%s",
|
|
|
|
|
PACKAGE_TARNAME,
|
|
|
|
|
kCPU,
|
|
|
|
|
PACKAGE_VERSION,
|
|
|
|
|
kOS);
|
|
|
|
|
|
2022-01-19 15:00:24 -05:00
|
|
|
|
#if BUILDFLAG(IS_MAC)
|
2014-11-05 18:15:19 -05:00
|
|
|
|
debug_build_string += base::StringPrintf(
|
|
|
|
|
",%d,%d",
|
2020-09-01 17:09:37 -04:00
|
|
|
|
AvailabilityVersionToMacOSVersionNumber(__MAC_OS_X_VERSION_MIN_REQUIRED),
|
|
|
|
|
AvailabilityVersionToMacOSVersionNumber(__MAC_OS_X_VERSION_MAX_ALLOWED));
|
2022-01-19 15:00:24 -05:00
|
|
|
|
#elif BUILDFLAG(IS_ANDROID)
|
2016-11-01 15:59:40 -04:00
|
|
|
|
debug_build_string += base::StringPrintf(",%d", __ANDROID_API__);
|
2014-11-05 18:15:19 -05:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return debug_build_string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace internal
|
2014-08-11 11:42:12 -07:00
|
|
|
|
|
|
|
|
|
MinidumpMiscInfoWriter::MinidumpMiscInfoWriter()
|
2017-03-01 12:59:24 -05:00
|
|
|
|
: MinidumpStreamWriter(), misc_info_(), has_xstate_data_(false) {
|
2014-08-11 11:42:12 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-10-27 15:01:39 -04:00
|
|
|
|
MinidumpMiscInfoWriter::~MinidumpMiscInfoWriter() {
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-05 18:15:19 -05:00
|
|
|
|
void MinidumpMiscInfoWriter::InitializeFromSnapshot(
|
|
|
|
|
const ProcessSnapshot* process_snapshot) {
|
|
|
|
|
DCHECK_EQ(state(), kStateMutable);
|
|
|
|
|
DCHECK_EQ(misc_info_.Flags1, 0u);
|
|
|
|
|
|
|
|
|
|
SetProcessID(InRangeCast<uint32_t>(process_snapshot->ProcessID(), 0));
|
|
|
|
|
|
|
|
|
|
const SystemSnapshot* system_snapshot = process_snapshot->System();
|
|
|
|
|
|
2016-08-10 23:51:20 -04:00
|
|
|
|
uint64_t current_hz;
|
|
|
|
|
uint64_t max_hz;
|
|
|
|
|
system_snapshot->CPUFrequency(¤t_hz, &max_hz);
|
2017-07-25 19:15:48 -04:00
|
|
|
|
constexpr uint32_t kHzPerMHz = static_cast<const uint32_t>(1E6);
|
2014-11-05 18:15:19 -05:00
|
|
|
|
SetProcessorPowerInfo(
|
2016-08-10 23:51:20 -04:00
|
|
|
|
InRangeCast<uint32_t>(current_hz / kHzPerMHz,
|
2014-11-05 18:15:19 -05:00
|
|
|
|
std::numeric_limits<uint32_t>::max()),
|
2016-08-10 23:51:20 -04:00
|
|
|
|
InRangeCast<uint32_t>(max_hz / kHzPerMHz,
|
2014-11-05 18:15:19 -05:00
|
|
|
|
std::numeric_limits<uint32_t>::max()),
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0);
|
|
|
|
|
|
|
|
|
|
timeval start_time;
|
|
|
|
|
process_snapshot->ProcessStartTime(&start_time);
|
|
|
|
|
|
|
|
|
|
timeval user_time;
|
|
|
|
|
timeval system_time;
|
|
|
|
|
process_snapshot->ProcessCPUTimes(&user_time, &system_time);
|
|
|
|
|
|
|
|
|
|
// Round the resource usage fields to the nearest second, because the minidump
|
|
|
|
|
// format only has one-second resolution. The start_time field is truncated
|
|
|
|
|
// instead of rounded so that the process uptime is reflected more accurately
|
|
|
|
|
// when the start time is compared to the snapshot time in the
|
|
|
|
|
// MINIDUMP_HEADER, which is also truncated, not rounded.
|
|
|
|
|
uint32_t user_seconds = TimevalToRoundedSeconds(user_time);
|
|
|
|
|
uint32_t system_seconds = TimevalToRoundedSeconds(system_time);
|
|
|
|
|
|
|
|
|
|
SetProcessTimes(start_time.tv_sec, user_seconds, system_seconds);
|
|
|
|
|
|
|
|
|
|
// This determines the system’s time zone, which may be different than the
|
|
|
|
|
// process’ notion of the time zone.
|
|
|
|
|
SystemSnapshot::DaylightSavingTimeStatus dst_status;
|
|
|
|
|
int standard_offset_seconds;
|
|
|
|
|
int daylight_offset_seconds;
|
|
|
|
|
std::string standard_name;
|
|
|
|
|
std::string daylight_name;
|
|
|
|
|
system_snapshot->TimeZone(&dst_status,
|
|
|
|
|
&standard_offset_seconds,
|
|
|
|
|
&daylight_offset_seconds,
|
|
|
|
|
&standard_name,
|
|
|
|
|
&daylight_name);
|
|
|
|
|
|
|
|
|
|
// standard_offset_seconds is seconds east of UTC, but the minidump file wants
|
|
|
|
|
// minutes west of UTC. daylight_offset_seconds is also seconds east of UTC,
|
|
|
|
|
// but the minidump file wants minutes west of the standard offset. The empty
|
|
|
|
|
// ({}) arguments are for the transition times in and out of daylight saving
|
|
|
|
|
// time. These are not determined because no API exists to do so, and the
|
|
|
|
|
// transition times may vary from year to year.
|
|
|
|
|
SetTimeZone(dst_status,
|
|
|
|
|
standard_offset_seconds / -60,
|
|
|
|
|
standard_name,
|
|
|
|
|
{},
|
|
|
|
|
0,
|
|
|
|
|
daylight_name,
|
|
|
|
|
{},
|
|
|
|
|
(standard_offset_seconds - daylight_offset_seconds) / 60);
|
|
|
|
|
|
|
|
|
|
SetBuildString(BuildString(system_snapshot),
|
|
|
|
|
internal::MinidumpMiscInfoDebugBuildString());
|
2022-05-14 22:40:24 -07:00
|
|
|
|
|
|
|
|
|
XSTATE_CONFIG_FEATURE_MSC_INFO xstate{};
|
|
|
|
|
if (MaybeSetXStateData(process_snapshot, &xstate)) {
|
|
|
|
|
SetXStateData(xstate);
|
|
|
|
|
}
|
2014-11-05 18:15:19 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MinidumpMiscInfoWriter::SetProcessID(uint32_t process_id) {
|
2014-08-11 11:42:12 -07:00
|
|
|
|
DCHECK_EQ(state(), kStateMutable);
|
|
|
|
|
|
|
|
|
|
misc_info_.ProcessId = process_id;
|
|
|
|
|
misc_info_.Flags1 |= MINIDUMP_MISC1_PROCESS_ID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MinidumpMiscInfoWriter::SetProcessTimes(time_t process_create_time,
|
|
|
|
|
uint32_t process_user_time,
|
|
|
|
|
uint32_t process_kernel_time) {
|
|
|
|
|
DCHECK_EQ(state(), kStateMutable);
|
|
|
|
|
|
|
|
|
|
internal::MinidumpWriterUtil::AssignTimeT(&misc_info_.ProcessCreateTime,
|
|
|
|
|
process_create_time);
|
|
|
|
|
|
|
|
|
|
misc_info_.ProcessUserTime = process_user_time;
|
|
|
|
|
misc_info_.ProcessKernelTime = process_kernel_time;
|
|
|
|
|
misc_info_.Flags1 |= MINIDUMP_MISC1_PROCESS_TIMES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MinidumpMiscInfoWriter::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) {
|
|
|
|
|
DCHECK_EQ(state(), kStateMutable);
|
|
|
|
|
|
|
|
|
|
misc_info_.ProcessorMaxMhz = processor_max_mhz;
|
|
|
|
|
misc_info_.ProcessorCurrentMhz = processor_current_mhz;
|
|
|
|
|
misc_info_.ProcessorMhzLimit = processor_mhz_limit;
|
|
|
|
|
misc_info_.ProcessorMaxIdleState = processor_max_idle_state;
|
|
|
|
|
misc_info_.ProcessorCurrentIdleState = processor_current_idle_state;
|
|
|
|
|
misc_info_.Flags1 |= MINIDUMP_MISC1_PROCESSOR_POWER_INFO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MinidumpMiscInfoWriter::SetProcessIntegrityLevel(
|
|
|
|
|
uint32_t process_integrity_level) {
|
|
|
|
|
DCHECK_EQ(state(), kStateMutable);
|
|
|
|
|
|
|
|
|
|
misc_info_.ProcessIntegrityLevel = process_integrity_level;
|
|
|
|
|
misc_info_.Flags1 |= MINIDUMP_MISC3_PROCESS_INTEGRITY;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MinidumpMiscInfoWriter::SetProcessExecuteFlags(
|
|
|
|
|
uint32_t process_execute_flags) {
|
|
|
|
|
DCHECK_EQ(state(), kStateMutable);
|
|
|
|
|
|
|
|
|
|
misc_info_.ProcessExecuteFlags = process_execute_flags;
|
|
|
|
|
misc_info_.Flags1 |= MINIDUMP_MISC3_PROCESS_EXECUTE_FLAGS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MinidumpMiscInfoWriter::SetProtectedProcess(uint32_t protected_process) {
|
|
|
|
|
DCHECK_EQ(state(), kStateMutable);
|
|
|
|
|
|
|
|
|
|
misc_info_.ProtectedProcess = protected_process;
|
|
|
|
|
misc_info_.Flags1 |= MINIDUMP_MISC3_PROTECTED_PROCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MinidumpMiscInfoWriter::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) {
|
|
|
|
|
DCHECK_EQ(state(), kStateMutable);
|
|
|
|
|
|
|
|
|
|
misc_info_.TimeZoneId = time_zone_id;
|
|
|
|
|
misc_info_.TimeZone.Bias = bias;
|
|
|
|
|
|
|
|
|
|
internal::MinidumpWriterUtil::AssignUTF8ToUTF16(
|
2020-09-12 09:20:14 +02:00
|
|
|
|
AsU16CStr(misc_info_.TimeZone.StandardName),
|
2022-02-28 20:57:19 -08:00
|
|
|
|
std::size(misc_info_.TimeZone.StandardName),
|
2014-08-11 11:42:12 -07:00
|
|
|
|
standard_name);
|
|
|
|
|
|
|
|
|
|
misc_info_.TimeZone.StandardDate = standard_date;
|
|
|
|
|
misc_info_.TimeZone.StandardBias = standard_bias;
|
|
|
|
|
|
|
|
|
|
internal::MinidumpWriterUtil::AssignUTF8ToUTF16(
|
2020-09-12 09:20:14 +02:00
|
|
|
|
AsU16CStr(misc_info_.TimeZone.DaylightName),
|
2022-02-28 20:57:19 -08:00
|
|
|
|
std::size(misc_info_.TimeZone.DaylightName),
|
2014-08-11 11:42:12 -07:00
|
|
|
|
daylight_name);
|
|
|
|
|
|
|
|
|
|
misc_info_.TimeZone.DaylightDate = daylight_date;
|
|
|
|
|
misc_info_.TimeZone.DaylightBias = daylight_bias;
|
|
|
|
|
|
|
|
|
|
misc_info_.Flags1 |= MINIDUMP_MISC3_TIMEZONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MinidumpMiscInfoWriter::SetBuildString(
|
|
|
|
|
const std::string& build_string,
|
|
|
|
|
const std::string& debug_build_string) {
|
|
|
|
|
DCHECK_EQ(state(), kStateMutable);
|
|
|
|
|
|
|
|
|
|
misc_info_.Flags1 |= MINIDUMP_MISC4_BUILDSTRING;
|
|
|
|
|
|
|
|
|
|
internal::MinidumpWriterUtil::AssignUTF8ToUTF16(
|
2020-09-12 09:20:14 +02:00
|
|
|
|
AsU16CStr(misc_info_.BuildString),
|
2022-02-28 20:57:19 -08:00
|
|
|
|
std::size(misc_info_.BuildString),
|
2020-09-12 09:20:14 +02:00
|
|
|
|
build_string);
|
2014-08-11 11:42:12 -07:00
|
|
|
|
internal::MinidumpWriterUtil::AssignUTF8ToUTF16(
|
2020-09-12 09:20:14 +02:00
|
|
|
|
AsU16CStr(misc_info_.DbgBldStr),
|
2022-02-28 20:57:19 -08:00
|
|
|
|
std::size(misc_info_.DbgBldStr),
|
2014-08-11 11:42:12 -07:00
|
|
|
|
debug_build_string);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-01 12:59:24 -05:00
|
|
|
|
void MinidumpMiscInfoWriter::SetXStateData(
|
|
|
|
|
const XSTATE_CONFIG_FEATURE_MSC_INFO& xstate_data) {
|
|
|
|
|
DCHECK_EQ(state(), kStateMutable);
|
|
|
|
|
|
|
|
|
|
misc_info_.XStateData = xstate_data;
|
|
|
|
|
has_xstate_data_ = true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-14 22:40:24 -07:00
|
|
|
|
bool MinidumpMiscInfoWriter::HasXStateData() const {
|
|
|
|
|
return has_xstate_data_;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-01 12:59:24 -05:00
|
|
|
|
void MinidumpMiscInfoWriter::SetProcessCookie(uint32_t process_cookie) {
|
|
|
|
|
DCHECK_EQ(state(), kStateMutable);
|
|
|
|
|
|
|
|
|
|
misc_info_.ProcessCookie = process_cookie;
|
|
|
|
|
misc_info_.Flags1 |= MINIDUMP_MISC5_PROCESS_COOKIE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-11 11:42:12 -07:00
|
|
|
|
bool MinidumpMiscInfoWriter::Freeze() {
|
|
|
|
|
DCHECK_EQ(state(), kStateMutable);
|
|
|
|
|
|
|
|
|
|
if (!MinidumpStreamWriter::Freeze()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t size = CalculateSizeOfObjectFromFlags();
|
|
|
|
|
if (!AssignIfInRange(&misc_info_.SizeOfInfo, size)) {
|
|
|
|
|
LOG(ERROR) << "size " << size << " out of range";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t MinidumpMiscInfoWriter::SizeOfObject() {
|
|
|
|
|
DCHECK_GE(state(), kStateFrozen);
|
|
|
|
|
|
|
|
|
|
return CalculateSizeOfObjectFromFlags();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MinidumpMiscInfoWriter::WriteObject(FileWriterInterface* file_writer) {
|
|
|
|
|
DCHECK_EQ(state(), kStateWritable);
|
|
|
|
|
|
|
|
|
|
return file_writer->Write(&misc_info_, CalculateSizeOfObjectFromFlags());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MinidumpStreamType MinidumpMiscInfoWriter::StreamType() const {
|
|
|
|
|
return kMinidumpStreamTypeMiscInfo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t MinidumpMiscInfoWriter::CalculateSizeOfObjectFromFlags() const {
|
|
|
|
|
DCHECK_GE(state(), kStateFrozen);
|
|
|
|
|
|
2017-03-01 12:59:24 -05:00
|
|
|
|
if (has_xstate_data_ || (misc_info_.Flags1 & MINIDUMP_MISC5_PROCESS_COOKIE)) {
|
|
|
|
|
return sizeof(MINIDUMP_MISC_INFO_5);
|
|
|
|
|
}
|
2014-08-11 11:42:12 -07:00
|
|
|
|
if (misc_info_.Flags1 & MINIDUMP_MISC4_BUILDSTRING) {
|
|
|
|
|
return sizeof(MINIDUMP_MISC_INFO_4);
|
|
|
|
|
}
|
|
|
|
|
if (misc_info_.Flags1 &
|
|
|
|
|
(MINIDUMP_MISC3_PROCESS_INTEGRITY | MINIDUMP_MISC3_PROCESS_EXECUTE_FLAGS |
|
|
|
|
|
MINIDUMP_MISC3_TIMEZONE | MINIDUMP_MISC3_PROTECTED_PROCESS)) {
|
|
|
|
|
return sizeof(MINIDUMP_MISC_INFO_3);
|
|
|
|
|
}
|
|
|
|
|
if (misc_info_.Flags1 & MINIDUMP_MISC1_PROCESSOR_POWER_INFO) {
|
|
|
|
|
return sizeof(MINIDUMP_MISC_INFO_2);
|
|
|
|
|
}
|
|
|
|
|
return sizeof(MINIDUMP_MISC_INFO);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace crashpad
|