1 // Copyright 2014 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 #ifndef CRASHPAD_MINIDUMP_MINIDUMP_THREAD_WRITER_H_
16 #define CRASHPAD_MINIDUMP_MINIDUMP_THREAD_WRITER_H_
17 
18 #include <windows.h>
19 #include <dbghelp.h>
20 #include <stdint.h>
21 #include <sys/types.h>
22 
23 #include <memory>
24 #include <vector>
25 
26 #include "base/macros.h"
27 #include "minidump/minidump_stream_writer.h"
28 #include "minidump/minidump_thread_id_map.h"
29 #include "minidump/minidump_writable.h"
30 
31 namespace crashpad {
32 
33 class MinidumpContextWriter;
34 class MinidumpMemoryListWriter;
35 class SnapshotMinidumpMemoryWriter;
36 class ThreadSnapshot;
37 
38 //! \brief The writer for a MINIDUMP_THREAD object in a minidump file.
39 //!
40 //! Because MINIDUMP_THREAD objects only appear as elements of
41 //! MINIDUMP_THREAD_LIST objects, this class does not write any data on its own.
42 //! It makes its MINIDUMP_THREAD data available to its MinidumpThreadListWriter
43 //! parent, which writes it as part of a MINIDUMP_THREAD_LIST.
44 class MinidumpThreadWriter final : public internal::MinidumpWritable {
45  public:
46   MinidumpThreadWriter();
47   ~MinidumpThreadWriter() override;
48 
49   //! \brief Initializes the MINIDUMP_THREAD based on \a thread_snapshot.
50   //!
51   //! \param[in] thread_snapshot The thread snapshot to use as source data.
52   //! \param[in] thread_id_map A MinidumpThreadIDMap to be consulted to
53   //!     determine the 32-bit minidump thread ID to use for \a thread_snapshot.
54   //!
55   //! \note Valid in #kStateMutable. No mutator methods may be called before
56   //!     this method, and it is not normally necessary to call any mutator
57   //!     methods after this method.
58   void InitializeFromSnapshot(const ThreadSnapshot* thread_snapshot,
59                               const MinidumpThreadIDMap* thread_id_map);
60 
61   //! \brief Returns a MINIDUMP_THREAD referencing this object’s data.
62   //!
63   //! This method is expected to be called by a MinidumpThreadListWriter in
64   //! order to obtain a MINIDUMP_THREAD to include in its list.
65   //!
66   //! \note Valid in #kStateWritable.
67   const MINIDUMP_THREAD* MinidumpThread() const;
68 
69   //! \brief Returns a SnapshotMinidumpMemoryWriter that will write the memory
70   //!     region corresponding to this object’s stack.
71   //!
72   //! If the thread does not have a stack, or its stack could not be determined,
73   //! this will return `nullptr`.
74   //!
75   //! This method is provided so that MinidumpThreadListWriter can obtain thread
76   //! stack memory regions for the purposes of adding them to a
77   //! MinidumpMemoryListWriter (configured by calling
78   //! MinidumpThreadListWriter::SetMemoryListWriter()) by calling
79   //! MinidumpMemoryListWriter::AddExtraMemory().
80   //!
81   //! \note Valid in any state.
Stack()82   SnapshotMinidumpMemoryWriter* Stack() const { return stack_.get(); }
83 
84   //! \brief Arranges for MINIDUMP_THREAD::Stack to point to the MINIDUMP_MEMORY
85   //!     object to be written by \a stack.
86   //!
87   //! This object takes ownership of \a stack and becomes its parent in the
88   //! overall tree of internal::MinidumpWritable objects.
89   //!
90   //! \note Valid in #kStateMutable.
91   void SetStack(std::unique_ptr<SnapshotMinidumpMemoryWriter> stack);
92 
93   //! \brief Arranges for MINIDUMP_THREAD::ThreadContext to point to the CPU
94   //!     context to be written by \a context.
95   //!
96   //! A context is required in all MINIDUMP_THREAD objects.
97   //!
98   //! This object takes ownership of \a context and becomes its parent in the
99   //! overall tree of internal::MinidumpWritable objects.
100   //!
101   //! \note Valid in #kStateMutable.
102   void SetContext(std::unique_ptr<MinidumpContextWriter> context);
103 
104   //! \brief Sets MINIDUMP_THREAD::ThreadId.
SetThreadID(uint32_t thread_id)105   void SetThreadID(uint32_t thread_id) { thread_.ThreadId = thread_id; }
106 
107   //! \brief Sets MINIDUMP_THREAD::SuspendCount.
SetSuspendCount(uint32_t suspend_count)108   void SetSuspendCount(uint32_t suspend_count) {
109     thread_.SuspendCount = suspend_count;
110   }
111 
112   //! \brief Sets MINIDUMP_THREAD::PriorityClass.
SetPriorityClass(uint32_t priority_class)113   void SetPriorityClass(uint32_t priority_class) {
114     thread_.PriorityClass = priority_class;
115   }
116 
117   //! \brief Sets MINIDUMP_THREAD::Priority.
SetPriority(uint32_t priority)118   void SetPriority(uint32_t priority) { thread_.Priority = priority; }
119 
120   //! \brief Sets MINIDUMP_THREAD::Teb.
SetTEB(uint64_t teb)121   void SetTEB(uint64_t teb) { thread_.Teb = teb; }
122 
123  protected:
124   // MinidumpWritable:
125   bool Freeze() override;
126   size_t SizeOfObject() override;
127   std::vector<MinidumpWritable*> Children() override;
128   bool WriteObject(FileWriterInterface* file_writer) override;
129 
130  private:
131   MINIDUMP_THREAD thread_;
132   std::unique_ptr<SnapshotMinidumpMemoryWriter> stack_;
133   std::unique_ptr<MinidumpContextWriter> context_;
134 
135   DISALLOW_COPY_AND_ASSIGN(MinidumpThreadWriter);
136 };
137 
138 //! \brief The writer for a MINIDUMP_THREAD_LIST stream in a minidump file,
139 //!     containing a list of MINIDUMP_THREAD objects.
140 class MinidumpThreadListWriter final : public internal::MinidumpStreamWriter {
141  public:
142   MinidumpThreadListWriter();
143   ~MinidumpThreadListWriter() override;
144 
145   //! \brief Adds an initialized MINIDUMP_THREAD for each thread in \a
146   //!     thread_snapshots to the MINIDUMP_THREAD_LIST.
147   //!
148   //! \param[in] thread_snapshots The thread snapshots to use as source data.
149   //! \param[out] thread_id_map A MinidumpThreadIDMap to be built by this
150   //!     method. This map must be empty when this method is called.
151   //!
152   //! \note Valid in #kStateMutable. AddThread() may not be called before this
153   //!     method, and it is not normally necessary to call AddThread() after
154   //!     this method.
155   void InitializeFromSnapshot(
156       const std::vector<const ThreadSnapshot*>& thread_snapshots,
157       MinidumpThreadIDMap* thread_id_map);
158 
159   //! \brief Sets the MinidumpMemoryListWriter that each thread’s stack memory
160   //!     region should be added to as extra memory.
161   //!
162   //! Each MINIDUMP_THREAD object can contain a reference to a
163   //! SnapshotMinidumpMemoryWriter object that contains a snapshot of its stac
164   //! memory. In the overall tree of internal::MinidumpWritable objects, these
165   //! SnapshotMinidumpMemoryWriter objects are considered children of their
166   //! MINIDUMP_THREAD, and are referenced by a MINIDUMP_MEMORY_DESCRIPTOR
167   //! contained in the MINIDUMP_THREAD. It is also possible for the same memory
168   //! regions to have MINIDUMP_MEMORY_DESCRIPTOR objects present in a
169   //! MINIDUMP_MEMORY_LIST stream. This is accomplished by calling this method,
170   //! which informs a MinidumpThreadListWriter that it should call
171   //! MinidumpMemoryListWriter::AddExtraMemory() for each extant thread stack
172   //! while the thread is being added in AddThread(). When this is done, the
173   //! MinidumpMemoryListWriter will contain a MINIDUMP_MEMORY_DESCRIPTOR
174   //! pointing to the thread’s stack memory in its MINIDUMP_MEMORY_LIST. Note
175   //! that the actual contents of the memory is only written once, as a child of
176   //! the MinidumpThreadWriter. The MINIDUMP_MEMORY_DESCRIPTOR objects in both
177   //! the MINIDUMP_THREAD and MINIDUMP_MEMORY_LIST will point to the same copy
178   //! of the memory’s contents.
179   //!
180   //! \note This method must be called before AddThread() is called. Threads
181   //!     added by AddThread() prior to this method being called will not have
182   //!     their stacks added to \a memory_list_writer as extra memory.
183   //! \note Valid in #kStateMutable.
184   void SetMemoryListWriter(MinidumpMemoryListWriter* memory_list_writer);
185 
186   //! \brief Adds a MinidumpThreadWriter to the MINIDUMP_THREAD_LIST.
187   //!
188   //! This object takes ownership of \a thread and becomes its parent in the
189   //! overall tree of internal::MinidumpWritable objects.
190   //!
191   //! \note Valid in #kStateMutable.
192   void AddThread(std::unique_ptr<MinidumpThreadWriter> thread);
193 
194  protected:
195   // MinidumpWritable:
196   bool Freeze() override;
197   size_t SizeOfObject() override;
198   std::vector<MinidumpWritable*> Children() override;
199   bool WriteObject(FileWriterInterface* file_writer) override;
200 
201   // MinidumpStreamWriter:
202   MinidumpStreamType StreamType() const override;
203 
204  private:
205   std::vector<std::unique_ptr<MinidumpThreadWriter>> threads_;
206   MinidumpMemoryListWriter* memory_list_writer_;  // weak
207   MINIDUMP_THREAD_LIST thread_list_base_;
208 
209   DISALLOW_COPY_AND_ASSIGN(MinidumpThreadListWriter);
210 };
211 
212 }  // namespace crashpad
213 
214 #endif  // CRASHPAD_MINIDUMP_MINIDUMP_THREAD_WRITER_H_
215