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