Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/crashpad_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ CrashpadInfo::CrashpadInfo()
crashpad_handler_behavior_(TriState::kUnset),
system_crash_reporter_forwarding_(TriState::kUnset),
gather_indirectly_referenced_memory_(TriState::kUnset),
padding_1_(0),
adjust_stack_capture_(TriState::kUnset),
extra_memory_ranges_(nullptr),
simple_annotations_(nullptr),
user_data_minidump_stream_head_(nullptr),
Expand Down
19 changes: 18 additions & 1 deletion client/crashpad_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,23 @@ struct CrashpadInfo {
indirectly_referenced_memory_cap_ = limit;
}

//! \brief Enables or disables adjusting stack capture based on stack pointer.
//!
//! 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 TriState::kUnset for this field will dictate whether
//! stack capture is adjusted.
//!
//! This causes Crashpad to calculate stack capture range based on the current
//! stack pointer instead of using TEB StackLimit/StackBase values. This is
//! useful when running under Wine/Proton where TEB values may be incorrect.
//!
//! \param[in] adjust_stack_capture Whether to adjust stack capture based on
//! the stack pointer.
void set_adjust_stack_capture(TriState adjust_stack_capture) {
adjust_stack_capture_ = adjust_stack_capture;
}

//! \brief Adds a custom stream to the minidump.
//!
//! The memory block referenced by \a data and \a size will added to the
Expand Down Expand Up @@ -329,7 +346,7 @@ struct CrashpadInfo {
TriState crashpad_handler_behavior_;
TriState system_crash_reporter_forwarding_;
TriState gather_indirectly_referenced_memory_;
uint8_t padding_1_;
TriState adjust_stack_capture_;
SimpleAddressRangeBag* extra_memory_ranges_; // weak
SimpleStringDictionary* simple_annotations_; // weak
internal::UserDataMinidumpStreamListEntry* user_data_minidump_stream_head_;
Expand Down
3 changes: 2 additions & 1 deletion snapshot/crashpad_info_client_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ CrashpadInfoClientOptions::CrashpadInfoClientOptions()
: crashpad_handler_behavior(TriState::kUnset),
system_crash_reporter_forwarding(TriState::kUnset),
gather_indirectly_referenced_memory(TriState::kUnset),
indirectly_referenced_memory_cap(0) {
indirectly_referenced_memory_cap(0),
adjust_stack_capture(TriState::kUnset) {
}

} // namespace crashpad
3 changes: 3 additions & 0 deletions snapshot/crashpad_info_client_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ struct CrashpadInfoClientOptions {

//! \sa CrashpadInfo::set_gather_indirectly_referenced_memory()
uint32_t indirectly_referenced_memory_cap;

//! \sa CrashpadInfo::set_adjust_stack_capture()
TriState adjust_stack_capture;
};

} // namespace crashpad
Expand Down
5 changes: 4 additions & 1 deletion snapshot/crashpad_types/crashpad_info_reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class CrashpadInfoReader::InfoContainerSpecific : public InfoContainer {
UnsetIfNotValidTriState(&info.crashpad_handler_behavior);
UnsetIfNotValidTriState(&info.system_crash_reporter_forwarding);
UnsetIfNotValidTriState(&info.gather_indirectly_referenced_memory);
UnsetIfNotValidTriState(&info.adjust_stack_capture);

return true;
}
Expand All @@ -109,7 +110,7 @@ class CrashpadInfoReader::InfoContainerSpecific : public InfoContainer {
TriState crashpad_handler_behavior;
TriState system_crash_reporter_forwarding;
TriState gather_indirectly_referenced_memory;
uint8_t padding_1;
TriState adjust_stack_capture;
typename Traits::Address extra_memory_ranges;
typename Traits::Address simple_annotations;
typename Traits::Address user_data_minidump_stream_head;
Expand Down Expand Up @@ -181,6 +182,8 @@ DEFINE_GETTER(uint32_t,
IndirectlyReferencedMemoryCap,
indirectly_referenced_memory_cap)

DEFINE_GETTER(TriState, AdjustStackCapture, adjust_stack_capture)

DEFINE_GETTER(VMAddress, ExtraMemoryRanges, extra_memory_ranges)

DEFINE_GETTER(VMAddress, SimpleAnnotations, simple_annotations)
Expand Down
1 change: 1 addition & 0 deletions snapshot/crashpad_types/crashpad_info_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class CrashpadInfoReader {
TriState SystemCrashReporterForwarding();
TriState GatherIndirectlyReferencedMemory();
uint32_t IndirectlyReferencedMemoryCap();
TriState AdjustStackCapture();
VMAddress ExtraMemoryRanges();
VMAddress SimpleAnnotations();
VMAddress AnnotationsList();
Expand Down
3 changes: 3 additions & 0 deletions snapshot/win/module_snapshot_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ void ModuleSnapshotWin::GetCrashpadOptionsInternal(
options->system_crash_reporter_forwarding = TriState::kUnset;
options->gather_indirectly_referenced_memory = TriState::kUnset;
options->indirectly_referenced_memory_cap = 0;
options->adjust_stack_capture = TriState::kUnset;
return;
}

Expand All @@ -270,6 +271,8 @@ void ModuleSnapshotWin::GetCrashpadOptionsInternal(
crashpad_info_->GatherIndirectlyReferencedMemory();
options->indirectly_referenced_memory_cap =
crashpad_info_->IndirectlyReferencedMemoryCap();
options->adjust_stack_capture =
crashpad_info_->AdjustStackCapture();
}

const VS_FIXEDFILEINFO* ModuleSnapshotWin::VSFixedFileInfo() const {
Expand Down
14 changes: 12 additions & 2 deletions snapshot/win/process_snapshot_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -245,12 +245,18 @@ const ProcessMemory* ProcessSnapshotWin::Memory() const {
void ProcessSnapshotWin::InitializeThreads(uint32_t* budget_remaining_pointer) {
const std::vector<ProcessReaderWin::Thread>& process_reader_threads =
process_reader_.Threads();

// Check if stack capture adjustment is enabled via CrashpadInfo
bool adjust_stack_capture =
options_.adjust_stack_capture == TriState::kEnabled;

for (const ProcessReaderWin::Thread& process_reader_thread :
process_reader_threads) {
auto thread = std::make_unique<internal::ThreadSnapshotWin>();
if (thread->Initialize(&process_reader_,
process_reader_thread,
budget_remaining_pointer)) {
budget_remaining_pointer,
adjust_stack_capture)) {
threads_.push_back(std::move(thread));
}
}
Expand Down Expand Up @@ -359,12 +365,16 @@ void ProcessSnapshotWin::GetCrashpadOptionsInternal(
local_options.indirectly_referenced_memory_cap =
module_options.indirectly_referenced_memory_cap;
}
if (local_options.adjust_stack_capture == TriState::kUnset) {
local_options.adjust_stack_capture = module_options.adjust_stack_capture;
}

// If non-default values have been found for all options, the loop can end
// early.
if (local_options.crashpad_handler_behavior != TriState::kUnset &&
local_options.system_crash_reporter_forwarding != TriState::kUnset &&
local_options.gather_indirectly_referenced_memory != TriState::kUnset) {
local_options.gather_indirectly_referenced_memory != TriState::kUnset &&
local_options.adjust_stack_capture != TriState::kUnset) {
break;
}
}
Expand Down
57 changes: 51 additions & 6 deletions snapshot/win/thread_snapshot_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,61 @@ ThreadSnapshotWin::~ThreadSnapshotWin() {}
bool ThreadSnapshotWin::Initialize(
ProcessReaderWin* process_reader,
const ProcessReaderWin::Thread& process_reader_thread,
uint32_t* gather_indirectly_referenced_memory_bytes_remaining) {
uint32_t* gather_indirectly_referenced_memory_bytes_remaining,
bool adjust_stack_capture) {
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);

thread_ = process_reader_thread;

WinVMAddress stack_capture_address = thread_.stack_region_address;
WinVMSize stack_capture_size = thread_.stack_region_size;

// If adjust_stack_capture is enabled, calculate stack range based on current
// SP
if (adjust_stack_capture) {
WinVMAddress sp = 0;
WinVMAddress stack_base =
thread_.stack_region_address + thread_.stack_region_size;

// Get the stack pointer from the context
#if defined(ARCH_CPU_X86)
sp = process_reader_thread.context.context<CONTEXT>()->Esp;
#elif defined(ARCH_CPU_X86_64)
if (process_reader->Is64Bit()) {
sp = process_reader_thread.context.context<CONTEXT>()->Rsp;
} else {
sp = process_reader_thread.context.context<WOW64_CONTEXT>()->Esp;
}
#elif defined(ARCH_CPU_ARM64)
sp = process_reader_thread.context.context<CONTEXT>()->Sp;
#endif

// Verify SP is within the valid stack region
if (sp >= thread_.stack_region_address && sp < stack_base) {
// Account for potential red zone (128 bytes for x86_64)
const WinVMSize red_zone_size =
#if defined(ARCH_CPU_X86_64)
process_reader->Is64Bit() ? 128 : 0;
#else
0;
#endif

// Adjust stack capture to start from SP (minus red zone) to stack base
WinVMAddress adjusted_start =
sp > red_zone_size ? sp - red_zone_size : sp;
if (adjusted_start >= thread_.stack_region_address &&
adjusted_start < stack_base) {
stack_capture_address = adjusted_start;
stack_capture_size = stack_base - adjusted_start;
}
}
}

if (process_reader->GetProcessInfo().LoggingRangeIsFullyReadable(
CheckedRange<WinVMAddress, WinVMSize>(thread_.stack_region_address,
thread_.stack_region_size))) {
stack_.Initialize(process_reader->Memory(),
thread_.stack_region_address,
thread_.stack_region_size);
CheckedRange<WinVMAddress, WinVMSize>(stack_capture_address,
stack_capture_size))) {
stack_.Initialize(
process_reader->Memory(), stack_capture_address, stack_capture_size);
} else {
stack_.Initialize(process_reader->Memory(), 0, 0);
}
Expand Down
5 changes: 4 additions & 1 deletion snapshot/win/thread_snapshot_win.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,16 @@ class ThreadSnapshotWin final : public ThreadSnapshot {
//! non-null, add extra memory regions to the snapshot pointed to by the
//! thread's stack. The size of the regions added is subtracted from the
//! count, and when it's `0`, no more regions will be added.
//! \param[in] adjust_stack_capture If `true`, adjust the stack capture
//! based on the current stack pointer instead of using TEB values.
//!
//! \return `true` if the snapshot could be created, `false` otherwise with
//! an appropriate message logged.
bool Initialize(
ProcessReaderWin* process_reader,
const ProcessReaderWin::Thread& process_reader_thread,
uint32_t* gather_indirectly_referenced_memory_bytes_remaining);
uint32_t* gather_indirectly_referenced_memory_bytes_remaining,
bool adjust_stack_capture = false);

// ThreadSnapshot:

Expand Down