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