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 25 LLDB_PLUGIN_DEFINE(ObjectFileMinidump) 26 27 void ObjectFileMinidump::Initialize() { 28 PluginManager::RegisterPlugin( 29 GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, 30 CreateMemoryInstance, GetModuleSpecifications, SaveCore); 31 } 32 33 void ObjectFileMinidump::Terminate() { 34 PluginManager::UnregisterPlugin(CreateInstance); 35 } 36 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 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 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 58 struct DumpFailRemoveHolder { 59 DumpFailRemoveHolder(MinidumpFileBuilder &builder) : m_builder(builder) {} 60 61 ~DumpFailRemoveHolder() { 62 if (!m_success) 63 m_builder.DeleteFile(); 64 } 65 66 void SetSuccess() { m_success = true; } 67 68 private: 69 MinidumpFileBuilder &m_builder; 70 bool m_success = false; 71 }; 72 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()); 78 assert(process_sp); 79 80 // Minidump defaults to stacks only. 81 if (options.GetStyle() == SaveCoreStyle::eSaveCoreUnspecified) 82 options.SetStyle(SaveCoreStyle::eSaveCoreStackOnly); 83 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()); 89 return false; 90 } 91 MinidumpFileBuilder builder(std::move(maybe_core_file.get()), process_sp, 92 options); 93 DumpFailRemoveHolder request(builder); 94 95 Log *log = GetLog(LLDBLog::Object); 96 error = builder.AddHeaderAndCalculateDirectories(); 97 if (error.Fail()) { 98 LLDB_LOGF(log, "AddHeaderAndCalculateDirectories failed: %s", 99 error.AsCString()); 100 return false; 101 }; 102 error = builder.AddSystemInfo(); 103 if (error.Fail()) { 104 LLDB_LOGF(log, "AddSystemInfo failed: %s", error.AsCString()); 105 return false; 106 } 107 108 error = builder.AddModuleList(); 109 if (error.Fail()) { 110 LLDB_LOGF(log, "AddModuleList failed: %s", error.AsCString()); 111 return false; 112 } 113 error = builder.AddMiscInfo(); 114 if (error.Fail()) { 115 LLDB_LOGF(log, "AddMiscInfo failed: %s", error.AsCString()); 116 return false; 117 } 118 119 error = builder.AddThreadList(); 120 if (error.Fail()) { 121 LLDB_LOGF(log, "AddThreadList failed: %s", error.AsCString()); 122 return false; 123 } 124 125 error = builder.AddLinuxFileStreams(); 126 if (error.Fail()) { 127 LLDB_LOGF(log, "AddLinuxFileStreams failed: %s", error.AsCString()); 128 return false; 129 } 130 131 // Add any exceptions but only if there are any in any threads. 132 error = builder.AddExceptions(); 133 if (error.Fail()) { 134 LLDB_LOGF(log, "AddExceptions failed: %s", error.AsCString()); 135 return false; 136 } 137 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(); 141 if (error.Fail()) { 142 LLDB_LOGF(log, "AddMemoryList failed: %s", error.AsCString()); 143 return false; 144 } 145 146 error = builder.DumpFile(); 147 if (error.Fail()) { 148 LLDB_LOGF(log, "DumpFile failed: %s", error.AsCString()); 149 return false; 150 } 151 152 request.SetSuccess(); 153 154 return true; 155 } 156