xref: /llvm-project/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp (revision 661382f2c07ba464caa0ad0fb8c64c1c3b20e9a4)
1eee687a6SAndrej Korman //===-- ObjectFileMinidump.cpp --------------------------------------------===//
2eee687a6SAndrej Korman //
3eee687a6SAndrej Korman // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4eee687a6SAndrej Korman // See https://llvm.org/LICENSE.txt for license information.
5eee687a6SAndrej Korman // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6eee687a6SAndrej Korman //
7eee687a6SAndrej Korman //===----------------------------------------------------------------------===//
8eee687a6SAndrej Korman 
9eee687a6SAndrej Korman #include "ObjectFileMinidump.h"
10eee687a6SAndrej Korman 
11eee687a6SAndrej Korman #include "MinidumpFileBuilder.h"
12eee687a6SAndrej Korman 
13eee687a6SAndrej Korman #include "lldb/Core/ModuleSpec.h"
14eee687a6SAndrej Korman #include "lldb/Core/PluginManager.h"
15eee687a6SAndrej Korman #include "lldb/Core/Section.h"
16eee687a6SAndrej Korman #include "lldb/Target/Process.h"
176870ac20Sjeffreytan81 #include "lldb/Utility/LLDBLog.h"
18a27164cbSJacob Lalonde #include "lldb/Utility/Log.h"
19eee687a6SAndrej Korman 
20eee687a6SAndrej Korman #include "llvm/Support/FileSystem.h"
21eee687a6SAndrej Korman 
22eee687a6SAndrej Korman using namespace lldb;
23eee687a6SAndrej Korman using namespace lldb_private;
24eee687a6SAndrej Korman 
25eee687a6SAndrej Korman LLDB_PLUGIN_DEFINE(ObjectFileMinidump)
26eee687a6SAndrej Korman 
27eee687a6SAndrej Korman void ObjectFileMinidump::Initialize() {
28eee687a6SAndrej Korman   PluginManager::RegisterPlugin(
29eee687a6SAndrej Korman       GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
30eee687a6SAndrej Korman       CreateMemoryInstance, GetModuleSpecifications, SaveCore);
31eee687a6SAndrej Korman }
32eee687a6SAndrej Korman 
33eee687a6SAndrej Korman void ObjectFileMinidump::Terminate() {
34eee687a6SAndrej Korman   PluginManager::UnregisterPlugin(CreateInstance);
35eee687a6SAndrej Korman }
36eee687a6SAndrej Korman 
37eee687a6SAndrej Korman ObjectFile *ObjectFileMinidump::CreateInstance(
38c69307e5SJonas Devlieghere     const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp,
39eee687a6SAndrej Korman     lldb::offset_t data_offset, const lldb_private::FileSpec *file,
40eee687a6SAndrej Korman     lldb::offset_t offset, lldb::offset_t length) {
41eee687a6SAndrej Korman   return nullptr;
42eee687a6SAndrej Korman }
43eee687a6SAndrej Korman 
44eee687a6SAndrej Korman ObjectFile *ObjectFileMinidump::CreateMemoryInstance(
45f2ea125eSJonas Devlieghere     const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp,
46eee687a6SAndrej Korman     const ProcessSP &process_sp, lldb::addr_t header_addr) {
47eee687a6SAndrej Korman   return nullptr;
48eee687a6SAndrej Korman }
49eee687a6SAndrej Korman 
50eee687a6SAndrej Korman size_t ObjectFileMinidump::GetModuleSpecifications(
51eee687a6SAndrej Korman     const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp,
52eee687a6SAndrej Korman     lldb::offset_t data_offset, lldb::offset_t file_offset,
53eee687a6SAndrej Korman     lldb::offset_t length, lldb_private::ModuleSpecList &specs) {
54eee687a6SAndrej Korman   specs.Clear();
55eee687a6SAndrej Korman   return 0;
56eee687a6SAndrej Korman }
57eee687a6SAndrej Korman 
58*661382f2SJacob Lalonde struct DumpFailRemoveHolder {
59*661382f2SJacob Lalonde   DumpFailRemoveHolder(MinidumpFileBuilder &builder) : m_builder(builder) {}
60*661382f2SJacob Lalonde 
61*661382f2SJacob Lalonde   ~DumpFailRemoveHolder() {
62*661382f2SJacob Lalonde     if (!m_success)
63*661382f2SJacob Lalonde       m_builder.DeleteFile();
64*661382f2SJacob Lalonde   }
65*661382f2SJacob Lalonde 
66*661382f2SJacob Lalonde   void SetSuccess() { m_success = true; }
67*661382f2SJacob Lalonde 
68*661382f2SJacob Lalonde private:
69*661382f2SJacob Lalonde   MinidumpFileBuilder &m_builder;
70*661382f2SJacob Lalonde   bool m_success = false;
71*661382f2SJacob Lalonde };
72*661382f2SJacob Lalonde 
73eee687a6SAndrej Korman bool ObjectFileMinidump::SaveCore(const lldb::ProcessSP &process_sp,
74572943e7SJacob Lalonde                                   lldb_private::SaveCoreOptions &options,
75eee687a6SAndrej Korman                                   lldb_private::Status &error) {
764120570dSJacob Lalonde   // Output file and process_sp are both checked in PluginManager::SaveCore.
774120570dSJacob Lalonde   assert(options.GetOutputFile().has_value());
784120570dSJacob Lalonde   assert(process_sp);
794120570dSJacob Lalonde 
804120570dSJacob Lalonde   // Minidump defaults to stacks only.
81572943e7SJacob Lalonde   if (options.GetStyle() == SaveCoreStyle::eSaveCoreUnspecified)
82572943e7SJacob Lalonde     options.SetStyle(SaveCoreStyle::eSaveCoreStackOnly);
83eee687a6SAndrej Korman 
84eee687a6SAndrej Korman   llvm::Expected<lldb::FileUP> maybe_core_file = FileSystem::Instance().Open(
854120570dSJacob Lalonde       options.GetOutputFile().value(),
864120570dSJacob Lalonde       File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate);
87eee687a6SAndrej Korman   if (!maybe_core_file) {
88a0dd90ebSAdrian Prantl     error = Status::FromError(maybe_core_file.takeError());
89eee687a6SAndrej Korman     return false;
90eee687a6SAndrej Korman   }
91572943e7SJacob Lalonde   MinidumpFileBuilder builder(std::move(maybe_core_file.get()), process_sp,
92572943e7SJacob Lalonde                               options);
93*661382f2SJacob Lalonde   DumpFailRemoveHolder request(builder);
94eee687a6SAndrej Korman 
95a27164cbSJacob Lalonde   Log *log = GetLog(LLDBLog::Object);
96a27164cbSJacob Lalonde   error = builder.AddHeaderAndCalculateDirectories();
97a27164cbSJacob Lalonde   if (error.Fail()) {
98a27164cbSJacob Lalonde     LLDB_LOGF(log, "AddHeaderAndCalculateDirectories failed: %s",
99a27164cbSJacob Lalonde               error.AsCString());
100eee687a6SAndrej Korman     return false;
101a27164cbSJacob Lalonde   };
102a27164cbSJacob Lalonde   error = builder.AddSystemInfo();
103a27164cbSJacob Lalonde   if (error.Fail()) {
104a27164cbSJacob Lalonde     LLDB_LOGF(log, "AddSystemInfo failed: %s", error.AsCString());
105a27164cbSJacob Lalonde     return false;
106a27164cbSJacob Lalonde   }
107a27164cbSJacob Lalonde 
108a27164cbSJacob Lalonde   error = builder.AddModuleList();
109a27164cbSJacob Lalonde   if (error.Fail()) {
110a27164cbSJacob Lalonde     LLDB_LOGF(log, "AddModuleList failed: %s", error.AsCString());
111a27164cbSJacob Lalonde     return false;
112a27164cbSJacob Lalonde   }
113a27164cbSJacob Lalonde   error = builder.AddMiscInfo();
114a27164cbSJacob Lalonde   if (error.Fail()) {
115a27164cbSJacob Lalonde     LLDB_LOGF(log, "AddMiscInfo failed: %s", error.AsCString());
116a27164cbSJacob Lalonde     return false;
117a27164cbSJacob Lalonde   }
118a27164cbSJacob Lalonde 
119a27164cbSJacob Lalonde   error = builder.AddThreadList();
120a27164cbSJacob Lalonde   if (error.Fail()) {
121a27164cbSJacob Lalonde     LLDB_LOGF(log, "AddThreadList failed: %s", error.AsCString());
122a27164cbSJacob Lalonde     return false;
123a27164cbSJacob Lalonde   }
124a27164cbSJacob Lalonde 
125a27164cbSJacob Lalonde   error = builder.AddLinuxFileStreams();
126a27164cbSJacob Lalonde   if (error.Fail()) {
127a27164cbSJacob Lalonde     LLDB_LOGF(log, "AddLinuxFileStreams failed: %s", error.AsCString());
128a27164cbSJacob Lalonde     return false;
129a27164cbSJacob Lalonde   }
130a27164cbSJacob Lalonde 
131a27164cbSJacob Lalonde   // Add any exceptions but only if there are any in any threads.
132a27164cbSJacob Lalonde   error = builder.AddExceptions();
133a27164cbSJacob Lalonde   if (error.Fail()) {
134a27164cbSJacob Lalonde     LLDB_LOGF(log, "AddExceptions failed: %s", error.AsCString());
135a27164cbSJacob Lalonde     return false;
136a27164cbSJacob Lalonde   }
137a27164cbSJacob Lalonde 
138a27164cbSJacob Lalonde   // Note: add memory HAS to be the last thing we do. It can overflow into 64b
139a27164cbSJacob Lalonde   // land and many RVA's only support 32b
140572943e7SJacob Lalonde   error = builder.AddMemoryList();
141a27164cbSJacob Lalonde   if (error.Fail()) {
142a27164cbSJacob Lalonde     LLDB_LOGF(log, "AddMemoryList failed: %s", error.AsCString());
143a27164cbSJacob Lalonde     return false;
144a27164cbSJacob Lalonde   }
145a27164cbSJacob Lalonde 
146a27164cbSJacob Lalonde   error = builder.DumpFile();
147a27164cbSJacob Lalonde   if (error.Fail()) {
148a27164cbSJacob Lalonde     LLDB_LOGF(log, "DumpFile failed: %s", error.AsCString());
149a27164cbSJacob Lalonde     return false;
150a27164cbSJacob Lalonde   }
151eee687a6SAndrej Korman 
152*661382f2SJacob Lalonde   request.SetSuccess();
153*661382f2SJacob Lalonde 
154eee687a6SAndrej Korman   return true;
155eee687a6SAndrej Korman }
156