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