1 //===-- ObjectFileMinidump.cpp --------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "ObjectFileMinidump.h"
11 #include "MinidumpFileBuilder.h"
13 #include "lldb/Core/ModuleSpec.h"
14 #include "lldb/Core/PluginManager.h"
15 #include "lldb/Core/Section.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Utility/LLDBLog.h"
18 #include "lldb/Utility/Log.h"
20 #include "llvm/Support/FileSystem.h"
23 using namespace lldb_private
;
25 LLDB_PLUGIN_DEFINE(ObjectFileMinidump
)
27 void ObjectFileMinidump::Initialize() {
28 PluginManager::RegisterPlugin(
29 GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance
,
30 CreateMemoryInstance
, GetModuleSpecifications
, SaveCore
);
33 void ObjectFileMinidump::Terminate() {
34 PluginManager::UnregisterPlugin(CreateInstance
);
37 ObjectFile
*ObjectFileMinidump::CreateInstance(
38 const lldb::ModuleSP
&module_sp
, lldb::DataBufferSP data_sp
,
39 lldb::offset_t data_offset
, const lldb_private::FileSpec
*file
,
40 lldb::offset_t offset
, lldb::offset_t length
) {
44 ObjectFile
*ObjectFileMinidump::CreateMemoryInstance(
45 const lldb::ModuleSP
&module_sp
, WritableDataBufferSP data_sp
,
46 const ProcessSP
&process_sp
, lldb::addr_t header_addr
) {
50 size_t ObjectFileMinidump::GetModuleSpecifications(
51 const lldb_private::FileSpec
&file
, lldb::DataBufferSP
&data_sp
,
52 lldb::offset_t data_offset
, lldb::offset_t file_offset
,
53 lldb::offset_t length
, lldb_private::ModuleSpecList
&specs
) {
58 struct DumpFailRemoveHolder
{
59 DumpFailRemoveHolder(MinidumpFileBuilder
&builder
) : m_builder(builder
) {}
61 ~DumpFailRemoveHolder() {
63 m_builder
.DeleteFile();
66 void SetSuccess() { m_success
= true; }
69 MinidumpFileBuilder
&m_builder
;
70 bool m_success
= false;
73 bool ObjectFileMinidump::SaveCore(const lldb::ProcessSP
&process_sp
,
74 lldb_private::SaveCoreOptions
&options
,
75 lldb_private::Status
&error
) {
76 // Output file and process_sp are both checked in PluginManager::SaveCore.
77 assert(options
.GetOutputFile().has_value());
80 // Minidump defaults to stacks only.
81 if (options
.GetStyle() == SaveCoreStyle::eSaveCoreUnspecified
)
82 options
.SetStyle(SaveCoreStyle::eSaveCoreStackOnly
);
84 llvm::Expected
<lldb::FileUP
> maybe_core_file
= FileSystem::Instance().Open(
85 options
.GetOutputFile().value(),
86 File::eOpenOptionWriteOnly
| File::eOpenOptionCanCreate
);
87 if (!maybe_core_file
) {
88 error
= Status::FromError(maybe_core_file
.takeError());
91 MinidumpFileBuilder
builder(std::move(maybe_core_file
.get()), process_sp
,
93 DumpFailRemoveHolder
request(builder
);
95 Log
*log
= GetLog(LLDBLog::Object
);
96 error
= builder
.AddHeaderAndCalculateDirectories();
98 LLDB_LOGF(log
, "AddHeaderAndCalculateDirectories failed: %s",
102 error
= builder
.AddSystemInfo();
104 LLDB_LOGF(log
, "AddSystemInfo failed: %s", error
.AsCString());
108 error
= builder
.AddModuleList();
110 LLDB_LOGF(log
, "AddModuleList failed: %s", error
.AsCString());
113 error
= builder
.AddMiscInfo();
115 LLDB_LOGF(log
, "AddMiscInfo failed: %s", error
.AsCString());
119 error
= builder
.AddThreadList();
121 LLDB_LOGF(log
, "AddThreadList failed: %s", error
.AsCString());
125 error
= builder
.AddLinuxFileStreams();
127 LLDB_LOGF(log
, "AddLinuxFileStreams failed: %s", error
.AsCString());
131 // Add any exceptions but only if there are any in any threads.
132 error
= builder
.AddExceptions();
134 LLDB_LOGF(log
, "AddExceptions failed: %s", error
.AsCString());
138 // Note: add memory HAS to be the last thing we do. It can overflow into 64b
139 // land and many RVA's only support 32b
140 error
= builder
.AddMemoryList();
142 LLDB_LOGF(log
, "AddMemoryList failed: %s", error
.AsCString());
146 error
= builder
.DumpFile();
148 LLDB_LOGF(log
, "DumpFile failed: %s", error
.AsCString());
152 request
.SetSuccess();