1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "snapshot/win/thread_snapshot_win.h"
16
17 #include <iterator>
18 #include <vector>
19
20 #include "base/check_op.h"
21 #include "snapshot/capture_memory.h"
22 #include "snapshot/win/capture_memory_delegate_win.h"
23 #include "snapshot/win/cpu_context_win.h"
24 #include "snapshot/win/process_reader_win.h"
25
26 namespace crashpad {
27 namespace internal {
28
ThreadSnapshotWin()29 ThreadSnapshotWin::ThreadSnapshotWin()
30 : ThreadSnapshot(),
31 context_(),
32 stack_(),
33 teb_(),
34 thread_(),
35 initialized_() {
36 }
37
~ThreadSnapshotWin()38 ThreadSnapshotWin::~ThreadSnapshotWin() {
39 }
40
Initialize(ProcessReaderWin * process_reader,const ProcessReaderWin::Thread & process_reader_thread,uint32_t * gather_indirectly_referenced_memory_bytes_remaining)41 bool ThreadSnapshotWin::Initialize(
42 ProcessReaderWin* process_reader,
43 const ProcessReaderWin::Thread& process_reader_thread,
44 uint32_t* gather_indirectly_referenced_memory_bytes_remaining) {
45 INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
46
47 thread_ = process_reader_thread;
48 if (process_reader->GetProcessInfo().LoggingRangeIsFullyReadable(
49 CheckedRange<WinVMAddress, WinVMSize>(thread_.stack_region_address,
50 thread_.stack_region_size))) {
51 stack_.Initialize(process_reader->Memory(),
52 thread_.stack_region_address,
53 thread_.stack_region_size);
54 } else {
55 stack_.Initialize(process_reader->Memory(), 0, 0);
56 }
57
58 if (process_reader->GetProcessInfo().LoggingRangeIsFullyReadable(
59 CheckedRange<WinVMAddress, WinVMSize>(thread_.teb_address,
60 thread_.teb_size))) {
61 teb_.Initialize(
62 process_reader->Memory(), thread_.teb_address, thread_.teb_size);
63 } else {
64 teb_.Initialize(process_reader->Memory(), 0, 0);
65 }
66
67 #if defined(ARCH_CPU_X86)
68 context_.architecture = kCPUArchitectureX86;
69 context_.x86 = &context_union_.x86;
70 InitializeX86Context(process_reader_thread.context.native, context_.x86);
71 #elif defined(ARCH_CPU_X86_64)
72 if (process_reader->Is64Bit()) {
73 context_.architecture = kCPUArchitectureX86_64;
74 context_.x86_64 = &context_union_.x86_64;
75 InitializeX64Context(process_reader_thread.context.native, context_.x86_64);
76 } else {
77 context_.architecture = kCPUArchitectureX86;
78 context_.x86 = &context_union_.x86;
79 InitializeX86Context(process_reader_thread.context.wow64, context_.x86);
80 }
81 #elif defined(ARCH_CPU_ARM64)
82 context_.architecture = kCPUArchitectureARM64;
83 context_.arm64 = &context_union_.arm64;
84 InitializeARM64Context(process_reader_thread.context.native, context_.arm64);
85 #else
86 #error Unsupported Windows Arch
87 #endif // ARCH_CPU_X86
88
89 CaptureMemoryDelegateWin capture_memory_delegate(
90 process_reader,
91 thread_,
92 &pointed_to_memory_,
93 gather_indirectly_referenced_memory_bytes_remaining);
94 CaptureMemory::PointedToByContext(context_, &capture_memory_delegate);
95 if (gather_indirectly_referenced_memory_bytes_remaining) {
96 CaptureMemory::PointedToByMemoryRange(stack_, &capture_memory_delegate);
97 }
98
99 INITIALIZATION_STATE_SET_VALID(initialized_);
100 return true;
101 }
102
Context() const103 const CPUContext* ThreadSnapshotWin::Context() const {
104 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
105 return &context_;
106 }
107
Stack() const108 const MemorySnapshot* ThreadSnapshotWin::Stack() const {
109 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
110 return &stack_;
111 }
112
ThreadID() const113 uint64_t ThreadSnapshotWin::ThreadID() const {
114 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
115 return thread_.id;
116 }
117
SuspendCount() const118 int ThreadSnapshotWin::SuspendCount() const {
119 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
120 return thread_.suspend_count;
121 }
122
Priority() const123 int ThreadSnapshotWin::Priority() const {
124 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
125 return thread_.priority;
126 }
127
ThreadSpecificDataAddress() const128 uint64_t ThreadSnapshotWin::ThreadSpecificDataAddress() const {
129 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
130 return thread_.teb_address;
131 }
132
ExtraMemory() const133 std::vector<const MemorySnapshot*> ThreadSnapshotWin::ExtraMemory() const {
134 INITIALIZATION_STATE_DCHECK_VALID(initialized_);
135 std::vector<const MemorySnapshot*> result;
136 result.reserve(1 + pointed_to_memory_.size());
137 result.push_back(&teb_);
138 for (const auto& pointed_to_memory : pointed_to_memory_) {
139 result.push_back(pointed_to_memory.get());
140 }
141 return result;
142 }
143
144 } // namespace internal
145 } // namespace crashpad
146