1 //===-- ObjectFileMinidump.cpp --------------------------------------------===//
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 #include "ObjectFileMinidump.h"
10
11 #include "MinidumpFileBuilder.h"
12
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"
19
20 #include "llvm/Support/FileSystem.h"
21
22 using namespace lldb;
23 using namespace lldb_private;
24
LLDB_PLUGIN_DEFINE(ObjectFileMinidump)25 LLDB_PLUGIN_DEFINE(ObjectFileMinidump)
26
27 void ObjectFileMinidump::Initialize() {
28 PluginManager::RegisterPlugin(
29 GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
30 CreateMemoryInstance, GetModuleSpecifications, SaveCore);
31 }
32
Terminate()33 void ObjectFileMinidump::Terminate() {
34 PluginManager::UnregisterPlugin(CreateInstance);
35 }
36
CreateInstance(const lldb::ModuleSP & module_sp,lldb::DataBufferSP data_sp,lldb::offset_t data_offset,const lldb_private::FileSpec * file,lldb::offset_t offset,lldb::offset_t length)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) {
41 return nullptr;
42 }
43
CreateMemoryInstance(const lldb::ModuleSP & module_sp,WritableDataBufferSP data_sp,const ProcessSP & process_sp,lldb::addr_t header_addr)44 ObjectFile *ObjectFileMinidump::CreateMemoryInstance(
45 const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp,
46 const ProcessSP &process_sp, lldb::addr_t header_addr) {
47 return nullptr;
48 }
49
GetModuleSpecifications(const lldb_private::FileSpec & file,lldb::DataBufferSP & data_sp,lldb::offset_t data_offset,lldb::offset_t file_offset,lldb::offset_t length,lldb_private::ModuleSpecList & specs)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) {
54 specs.Clear();
55 return 0;
56 }
57
SaveCore(const lldb::ProcessSP & process_sp,const lldb_private::SaveCoreOptions & options,lldb_private::Status & error)58 bool ObjectFileMinidump::SaveCore(const lldb::ProcessSP &process_sp,
59 const lldb_private::SaveCoreOptions &options,
60 lldb_private::Status &error) {
61 // Output file and process_sp are both checked in PluginManager::SaveCore.
62 assert(options.GetOutputFile().has_value());
63 assert(process_sp);
64
65 // Minidump defaults to stacks only.
66 SaveCoreStyle core_style = options.GetStyle();
67 if (core_style == SaveCoreStyle::eSaveCoreUnspecified)
68 core_style = SaveCoreStyle::eSaveCoreStackOnly;
69
70 llvm::Expected<lldb::FileUP> maybe_core_file = FileSystem::Instance().Open(
71 options.GetOutputFile().value(),
72 File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate);
73 if (!maybe_core_file) {
74 error = maybe_core_file.takeError();
75 return false;
76 }
77 MinidumpFileBuilder builder(std::move(maybe_core_file.get()), process_sp);
78
79 Log *log = GetLog(LLDBLog::Object);
80 error = builder.AddHeaderAndCalculateDirectories();
81 if (error.Fail()) {
82 LLDB_LOGF(log, "AddHeaderAndCalculateDirectories failed: %s",
83 error.AsCString());
84 return false;
85 };
86 error = builder.AddSystemInfo();
87 if (error.Fail()) {
88 LLDB_LOGF(log, "AddSystemInfo failed: %s", error.AsCString());
89 return false;
90 }
91
92 error = builder.AddModuleList();
93 if (error.Fail()) {
94 LLDB_LOGF(log, "AddModuleList failed: %s", error.AsCString());
95 return false;
96 }
97 error = builder.AddMiscInfo();
98 if (error.Fail()) {
99 LLDB_LOGF(log, "AddMiscInfo failed: %s", error.AsCString());
100 return false;
101 }
102
103 error = builder.AddThreadList();
104 if (error.Fail()) {
105 LLDB_LOGF(log, "AddThreadList failed: %s", error.AsCString());
106 return false;
107 }
108
109 error = builder.AddLinuxFileStreams();
110 if (error.Fail()) {
111 LLDB_LOGF(log, "AddLinuxFileStreams failed: %s", error.AsCString());
112 return false;
113 }
114
115 // Add any exceptions but only if there are any in any threads.
116 error = builder.AddExceptions();
117 if (error.Fail()) {
118 LLDB_LOGF(log, "AddExceptions failed: %s", error.AsCString());
119 return false;
120 }
121
122 // Note: add memory HAS to be the last thing we do. It can overflow into 64b
123 // land and many RVA's only support 32b
124 error = builder.AddMemoryList(core_style);
125 if (error.Fail()) {
126 LLDB_LOGF(log, "AddMemoryList failed: %s", error.AsCString());
127 return false;
128 }
129
130 error = builder.DumpFile();
131 if (error.Fail()) {
132 LLDB_LOGF(log, "DumpFile failed: %s", error.AsCString());
133 return false;
134 }
135
136 return true;
137 }
138