Files
clang-p2996/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp
jeffreytan81 6870ac201f Fix saving minidump from lldb-dap (#89113)
There are users reporting saving minidump from lldb-dap does not work.

Turns out our stack trace request always evaluate a function call which
caused JIT object file like "__lldb_caller_function" to be created which
can fail minidump builder to get its module size.

This patch fixes "getModuleFileSize" for ObjectFileJIT so that module
list can be saved. I decided to create a lldb-dap test so that this
end-to-end functionality can be validated from our tests (instead of
only command line lldb).

The patch also improves several other small things in the workflow:
1. It logs any minidump stream failure so that it is easier to find out
what stream saving fails. In future, we should show process and error to
end users.
2. It handles error from "getModuleFileSize" llvm::Expected<T> otherwise
it will complain the error is not handled.

---------

Co-authored-by: jeffreytan81 <jeffreytan@fb.com>
2024-04-18 09:24:33 -07:00

121 lines
3.6 KiB
C++

//===-- ObjectFileMinidump.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "ObjectFileMinidump.h"
#include "MinidumpFileBuilder.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/LLDBLog.h"
#include "llvm/Support/FileSystem.h"
using namespace lldb;
using namespace lldb_private;
LLDB_PLUGIN_DEFINE(ObjectFileMinidump)
void ObjectFileMinidump::Initialize() {
PluginManager::RegisterPlugin(
GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
CreateMemoryInstance, GetModuleSpecifications, SaveCore);
}
void ObjectFileMinidump::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
ObjectFile *ObjectFileMinidump::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) {
return nullptr;
}
ObjectFile *ObjectFileMinidump::CreateMemoryInstance(
const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp,
const ProcessSP &process_sp, lldb::addr_t header_addr) {
return nullptr;
}
size_t ObjectFileMinidump::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) {
specs.Clear();
return 0;
}
bool ObjectFileMinidump::SaveCore(const lldb::ProcessSP &process_sp,
const lldb_private::FileSpec &outfile,
lldb::SaveCoreStyle &core_style,
lldb_private::Status &error) {
// Set default core style if it isn't set.
if (core_style == SaveCoreStyle::eSaveCoreUnspecified)
core_style = SaveCoreStyle::eSaveCoreStackOnly;
if (!process_sp)
return false;
MinidumpFileBuilder builder;
Target &target = process_sp->GetTarget();
Log *log = GetLog(LLDBLog::Object);
error = builder.AddSystemInfo(target.GetArchitecture().GetTriple());
if (error.Fail()) {
LLDB_LOG(log, "AddSystemInfo failed: %s", error.AsCString());
return false;
}
error = builder.AddModuleList(target);
if (error.Fail()) {
LLDB_LOG(log, "AddModuleList failed: %s", error.AsCString());
return false;
}
builder.AddMiscInfo(process_sp);
error = builder.AddThreadList(process_sp);
if (error.Fail()) {
LLDB_LOG(log, "AddThreadList failed: %s", error.AsCString());
return false;
}
// Add any exceptions but only if there are any in any threads.
builder.AddExceptions(process_sp);
error = builder.AddMemoryList(process_sp, core_style);
if (error.Fail()) {
LLDB_LOG(log, "AddMemoryList failed: %s", error.AsCString());
return false;
}
if (target.GetArchitecture().GetTriple().getOS() ==
llvm::Triple::OSType::Linux) {
builder.AddLinuxFileStreams(process_sp);
}
llvm::Expected<lldb::FileUP> maybe_core_file = FileSystem::Instance().Open(
outfile, File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate);
if (!maybe_core_file) {
error = maybe_core_file.takeError();
return false;
}
lldb::FileUP core_file = std::move(maybe_core_file.get());
error = builder.Dump(core_file);
if (error.Fail())
return false;
return true;
}