1 //===-- MinidumpFileBuilder.h ---------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// \file 10 /// Structure holding data neccessary for minidump file creation. 11 /// 12 /// The class MinidumpFileWriter is used to hold the data that will eventually 13 /// be dumped to the file. 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_MINIDUMPFILEBUILDER_H 17 #define LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_MINIDUMPFILEBUILDER_H 18 19 #include <cstddef> 20 #include <cstdint> 21 #include <map> 22 #include <unordered_map> 23 #include <utility> 24 #include <variant> 25 26 #include "lldb/Core/Progress.h" 27 #include "lldb/Symbol/SaveCoreOptions.h" 28 #include "lldb/Target/Process.h" 29 #include "lldb/Target/Target.h" 30 #include "lldb/Utility/DataBufferHeap.h" 31 #include "lldb/Utility/Status.h" 32 #include "lldb/lldb-forward.h" 33 #include "lldb/lldb-types.h" 34 35 #include "llvm/BinaryFormat/Minidump.h" 36 #include "llvm/Object/Minidump.h" 37 38 // Write std::string to minidump in the UTF16 format(with null termination char) 39 // with the size(without null termination char) preceding the UTF16 string. 40 // Empty strings are also printed with zero length and just null termination 41 // char. 42 lldb_private::Status WriteString(const std::string &to_write, 43 lldb_private::DataBufferHeap *buffer); 44 45 /// \class MinidumpFileBuilder 46 /// Minidump writer for Linux 47 /// 48 /// This class provides a Minidump writer that is able to 49 /// snapshot the current process state. 50 /// 51 /// Minidumps are a Microsoft format for dumping process state. 52 /// This class constructs the minidump on disk starting with 53 /// Headers and Directories are written at the top of the file, 54 /// with the amount of bytes being precalculates before any writing takes place 55 /// Then the smaller data sections are written 56 /// SystemInfo, ModuleList, Misc Info. 57 /// Then Threads are emitted, threads are the first section that needs to be 58 /// 'fixed up' this happens when later we emit the memory stream, we identify if 59 /// that stream is the expected stack, and if so we update the stack with the 60 /// current RVA. Lastly the Memory lists are added. For Memory List, this will 61 /// contain everything that can fit within 4.2gb. MemoryList has it's 62 /// descriptors written at the end so it cannot be allowed to overflow. 63 /// 64 /// Memory64List is a special case where it has to be begin before 4.2gb but can 65 /// expand forever The difference in Memory64List is there are no RVA's and all 66 /// the addresses are figured out by starting at the base RVA, and adding the 67 /// antecedent memory sections. 68 /// 69 /// Because Memory64List can be arbitrarily large, this class has to write 70 /// chunks to disk this means we have to precalculate the descriptors and write 71 /// them first, and if we encounter any error, or are unable to read the same 72 /// number of bytes we have to go back and update them on disk. 73 /// 74 /// And as the last step, after all the directories have been added, we go back 75 /// to the top of the file to fill in the header and the redirectory sections 76 /// that we preallocated. 77 class MinidumpFileBuilder { 78 public: 79 MinidumpFileBuilder(lldb::FileUP &&core_file, 80 const lldb::ProcessSP &process_sp, 81 lldb_private::SaveCoreOptions &save_core_options) 82 : m_process_sp(process_sp), m_core_file(std::move(core_file)), 83 m_save_core_options(save_core_options) {} 84 85 MinidumpFileBuilder(const MinidumpFileBuilder &) = delete; 86 MinidumpFileBuilder &operator=(const MinidumpFileBuilder &) = delete; 87 88 MinidumpFileBuilder(MinidumpFileBuilder &&other) = default; 89 MinidumpFileBuilder &operator=(MinidumpFileBuilder &&other) = default; 90 91 ~MinidumpFileBuilder() = default; 92 93 // This method only calculates the amount of bytes the header and directories 94 // will take up. It does not write the directories or headers. This function 95 // must be called with a followup to fill in the data. 96 lldb_private::Status AddHeaderAndCalculateDirectories(); 97 // Add SystemInfo stream, used for storing the most basic information 98 // about the system, platform etc... 99 lldb_private::Status AddSystemInfo(); 100 // Add ModuleList stream, containing information about all loaded modules 101 // at the time of saving minidump. 102 lldb_private::Status AddModuleList(); 103 // Add ThreadList stream, containing information about all threads running 104 // at the moment of core saving. Contains information about thread 105 // contexts. 106 lldb_private::Status AddThreadList(); 107 // Add Exception streams for any threads that stopped with exceptions. 108 lldb_private::Status AddExceptions(); 109 // Add MemoryList stream, containing dumps of important memory segments 110 lldb_private::Status AddMemoryList(); 111 // Add MiscInfo stream, mainly providing ProcessId 112 lldb_private::Status AddMiscInfo(); 113 // Add informative files about a Linux process 114 lldb_private::Status AddLinuxFileStreams(); 115 116 // Run cleanup and write all remaining bytes to file 117 lldb_private::Status DumpFile(); 118 119 // Delete the file if it exists 120 void DeleteFile() noexcept; 121 122 private: 123 lldb_private::Status AddLLDBGeneratedStream(); 124 // Add data to the end of the buffer, if the buffer exceeds the flush level, 125 // trigger a flush. 126 lldb_private::Status AddData(const void *data, uint64_t size); 127 // Add MemoryList stream, containing dumps of important memory segments 128 lldb_private::Status 129 AddMemoryList_64(std::vector<lldb_private::CoreFileMemoryRange> &ranges, 130 lldb_private::Progress &progress); 131 lldb_private::Status 132 AddMemoryList_32(std::vector<lldb_private::CoreFileMemoryRange> &ranges, 133 lldb_private::Progress &progress); 134 // Update the thread list on disk with the newly emitted stack RVAs. 135 lldb_private::Status FixThreadStacks(); 136 lldb_private::Status FlushBufferToDisk(); 137 138 lldb_private::Status DumpHeader() const; 139 lldb_private::Status DumpDirectories() const; 140 // Add directory of StreamType pointing to the current end of the prepared 141 // file with the specified size. 142 lldb_private::Status AddDirectory(llvm::minidump::StreamType type, 143 uint64_t stream_size); 144 lldb::offset_t GetCurrentDataEndOffset() const; 145 // Stores directories to fill in later 146 std::vector<llvm::minidump::Directory> m_directories; 147 // When we write off the threads for the first time, we need to clean them up 148 // and give them the correct RVA once we write the stack memory list. 149 // We save by the end because we only take from the stack pointer up 150 // So the saved off range base can differ from the memory region the stack 151 // pointer is in. 152 std::unordered_map<lldb::addr_t, llvm::minidump::Thread> 153 m_thread_by_range_end; 154 // Main data buffer consisting of data without the minidump header and 155 // directories 156 lldb_private::DataBufferHeap m_data; 157 lldb::ProcessSP m_process_sp; 158 159 size_t m_expected_directories = 0; 160 uint64_t m_saved_data_size = 0; 161 lldb::offset_t m_thread_list_start = 0; 162 // We set the max write amount to 128 mb, this is arbitrary 163 // but we want to try to keep the size of m_data small 164 // and we will only exceed a 128 mb buffer if we get a memory region 165 // that is larger than 128 mb. 166 static constexpr size_t MAX_WRITE_CHUNK_SIZE = (1024 * 1024 * 128); 167 168 static constexpr size_t HEADER_SIZE = sizeof(llvm::minidump::Header); 169 static constexpr size_t DIRECTORY_SIZE = sizeof(llvm::minidump::Directory); 170 171 // More that one place can mention the register thread context locations, 172 // so when we emit the thread contents, remember where it is so we don't have 173 // to duplicate it in the exception data. 174 std::unordered_map<lldb::tid_t, llvm::minidump::LocationDescriptor> 175 m_tid_to_reg_ctx; 176 lldb::FileUP m_core_file; 177 lldb_private::SaveCoreOptions m_save_core_options; 178 }; 179 #endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_MINIDUMP_MINIDUMPFILEBUILDER_H 180