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>
121 lines
3.6 KiB
C++
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;
|
|
}
|