forked from OSchip/llvm-project
parent
4d5d1dd6d5
commit
af75dab383
|
@ -341,6 +341,10 @@ public:
|
||||||
bool
|
bool
|
||||||
IsInstrumentationRuntimePresent(InstrumentationRuntimeType type);
|
IsInstrumentationRuntimePresent(InstrumentationRuntimeType type);
|
||||||
|
|
||||||
|
// Save the state of the process in a core file (or mini dump on Windows).
|
||||||
|
lldb::SBError
|
||||||
|
SaveCore(const char *file_name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class SBAddress;
|
friend class SBAddress;
|
||||||
friend class SBBreakpoint;
|
friend class SBBreakpoint;
|
||||||
|
|
|
@ -180,6 +180,9 @@ public:
|
||||||
bool stop_at_entry,
|
bool stop_at_entry,
|
||||||
lldb::SBError& error);
|
lldb::SBError& error);
|
||||||
|
|
||||||
|
SBProcess
|
||||||
|
LoadCore (const char *core_file);
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
/// Launch a new process with sensible defaults.
|
/// Launch a new process with sensible defaults.
|
||||||
///
|
///
|
||||||
|
@ -214,9 +217,6 @@ public:
|
||||||
SBProcess
|
SBProcess
|
||||||
Launch (SBLaunchInfo &launch_info, SBError& error);
|
Launch (SBLaunchInfo &launch_info, SBError& error);
|
||||||
|
|
||||||
SBProcess
|
|
||||||
LoadCore (const char *core_file);
|
|
||||||
|
|
||||||
SBProcess
|
SBProcess
|
||||||
Attach (SBAttachInfo &attach_info, SBError& error);
|
Attach (SBAttachInfo &attach_info, SBError& error);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
LEVEL = ../../make
|
||||||
|
|
||||||
|
CXX_SOURCES := main.cpp
|
||||||
|
|
||||||
|
include $(LEVEL)/Makefile.rules
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
"""
|
||||||
|
Test saving a core file (or mini dump).
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import os, time
|
||||||
|
import lldb
|
||||||
|
from lldbsuite.test.lldbtest import *
|
||||||
|
|
||||||
|
class ProcessSaveCoreTestCase(TestBase):
|
||||||
|
|
||||||
|
mydir = TestBase.compute_mydir(__file__)
|
||||||
|
|
||||||
|
@not_remote_testsuite_ready
|
||||||
|
@skipIf(oslist=not_in(['windows']))
|
||||||
|
def test_cannot_save_core_unless_process_stopped(self):
|
||||||
|
"""Test that SaveCore fails if the process isn't stopped."""
|
||||||
|
self.build()
|
||||||
|
exe = os.path.join(os.getcwd(), "a.out")
|
||||||
|
core = os.path.join(os.getcwd(), "core.dmp")
|
||||||
|
target = self.dbg.CreateTarget(exe)
|
||||||
|
process = target.LaunchSimple(None, None, self.get_process_working_directory())
|
||||||
|
self.assertNotEqual(process.GetState(), lldb.eStateStopped)
|
||||||
|
error = process.SaveCore(core)
|
||||||
|
self.assertTrue(error.Fail())
|
||||||
|
|
||||||
|
@not_remote_testsuite_ready
|
||||||
|
@skipIf(oslist=not_in(['windows']))
|
||||||
|
def test_save_windows_mini_dump(self):
|
||||||
|
"""Test that we can save a Windows mini dump."""
|
||||||
|
self.build()
|
||||||
|
exe = os.path.join(os.getcwd(), "a.out")
|
||||||
|
core = os.path.join(os.getcwd(), "core.dmp")
|
||||||
|
try:
|
||||||
|
target = self.dbg.CreateTarget(exe)
|
||||||
|
breakpoint = target.BreakpointCreateByName("bar")
|
||||||
|
process = target.LaunchSimple(None, None, self.get_process_working_directory())
|
||||||
|
self.assertEqual(process.GetState(), lldb.eStateStopped)
|
||||||
|
self.assertTrue(process.SaveCore(core))
|
||||||
|
self.assertTrue(os.path.isfile(core))
|
||||||
|
self.assertTrue(process.Kill().Success())
|
||||||
|
|
||||||
|
# To verify, we'll launch with the mini dump, and ensure that we see
|
||||||
|
# the executable in the module list.
|
||||||
|
target = self.dbg.CreateTarget(None)
|
||||||
|
process = target.LoadCore(core)
|
||||||
|
files = [target.GetModuleAtIndex(i).GetFileSpec() for i in range(0, target.GetNumModules())]
|
||||||
|
paths = [os.path.join(f.GetDirectory(), f.GetFilename()) for f in files]
|
||||||
|
self.assertTrue(exe in paths)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# Clean up the mini dump file.
|
||||||
|
self.assertTrue(self.dbg.DeleteTarget(target))
|
||||||
|
if (os.path.isfile(core)):
|
||||||
|
os.unlink(core)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
int global = 42;
|
||||||
|
|
||||||
|
int
|
||||||
|
bar(int x)
|
||||||
|
{
|
||||||
|
int y = 4*x + global;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
foo(int x)
|
||||||
|
{
|
||||||
|
int y = 2*bar(3*x);
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
return 0 * foo(1);
|
||||||
|
}
|
|
@ -398,6 +398,9 @@ public:
|
||||||
bool
|
bool
|
||||||
IsInstrumentationRuntimePresent(lldb::InstrumentationRuntimeType type);
|
IsInstrumentationRuntimePresent(lldb::InstrumentationRuntimeType type);
|
||||||
|
|
||||||
|
lldb::SBError
|
||||||
|
SaveCore(const char *file_name);
|
||||||
|
|
||||||
%pythoncode %{
|
%pythoncode %{
|
||||||
def __get_is_alive__(self):
|
def __get_is_alive__(self):
|
||||||
'''Returns "True" if the process is currently alive, "False" otherwise'''
|
'''Returns "True" if the process is currently alive, "False" otherwise'''
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "lldb/Core/Debugger.h"
|
#include "lldb/Core/Debugger.h"
|
||||||
#include "lldb/Core/Log.h"
|
#include "lldb/Core/Log.h"
|
||||||
#include "lldb/Core/Module.h"
|
#include "lldb/Core/Module.h"
|
||||||
|
#include "lldb/Core/PluginManager.h"
|
||||||
#include "lldb/Core/State.h"
|
#include "lldb/Core/State.h"
|
||||||
#include "lldb/Core/Stream.h"
|
#include "lldb/Core/Stream.h"
|
||||||
#include "lldb/Core/StreamFile.h"
|
#include "lldb/Core/StreamFile.h"
|
||||||
|
@ -1425,3 +1426,27 @@ SBProcess::IsInstrumentationRuntimePresent(InstrumentationRuntimeType type)
|
||||||
|
|
||||||
return runtime_sp->IsActive();
|
return runtime_sp->IsActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lldb::SBError
|
||||||
|
SBProcess::SaveCore(const char *file_name)
|
||||||
|
{
|
||||||
|
lldb::SBError error;
|
||||||
|
ProcessSP process_sp(GetSP());
|
||||||
|
if (!process_sp)
|
||||||
|
{
|
||||||
|
error.SetErrorString("SBProcess is invalid");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex::Locker api_locker(process_sp->GetTarget().GetAPIMutex());
|
||||||
|
|
||||||
|
if (process_sp->GetState() != eStateStopped)
|
||||||
|
{
|
||||||
|
error.SetErrorString("the process is not stopped");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileSpec core_file(file_name, false);
|
||||||
|
error.ref() = PluginManager::SaveCore(process_sp, core_file);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
|
@ -256,7 +256,7 @@ protected:
|
||||||
{
|
{
|
||||||
if (!symfile.Readable())
|
if (!symfile.Readable())
|
||||||
{
|
{
|
||||||
result.AppendErrorWithFormat("symbol file '%s' is not readable", core_file.GetPath().c_str());
|
result.AppendErrorWithFormat("symbol file '%s' is not readable", symfile.GetPath().c_str());
|
||||||
result.SetStatus (eReturnStatusFailed);
|
result.SetStatus (eReturnStatusFailed);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
add_lldb_library(lldbPluginObjectFilePECOFF
|
add_lldb_library(lldbPluginObjectFilePECOFF
|
||||||
ObjectFilePECOFF.cpp
|
ObjectFilePECOFF.cpp
|
||||||
|
WindowsMiniDump.cpp
|
||||||
)
|
)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "ObjectFilePECOFF.h"
|
#include "ObjectFilePECOFF.h"
|
||||||
|
#include "WindowsMiniDump.h"
|
||||||
|
|
||||||
#include "llvm/Support/COFF.h"
|
#include "llvm/Support/COFF.h"
|
||||||
|
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
#include "lldb/Core/Timer.h"
|
#include "lldb/Core/Timer.h"
|
||||||
#include "lldb/Core/UUID.h"
|
#include "lldb/Core/UUID.h"
|
||||||
#include "lldb/Symbol/ObjectFile.h"
|
#include "lldb/Symbol/ObjectFile.h"
|
||||||
|
#include "lldb/Target/Process.h"
|
||||||
#include "lldb/Target/SectionLoadList.h"
|
#include "lldb/Target/SectionLoadList.h"
|
||||||
#include "lldb/Target/Target.h"
|
#include "lldb/Target/Target.h"
|
||||||
|
|
||||||
|
@ -42,7 +44,8 @@ ObjectFilePECOFF::Initialize()
|
||||||
GetPluginDescriptionStatic(),
|
GetPluginDescriptionStatic(),
|
||||||
CreateInstance,
|
CreateInstance,
|
||||||
CreateMemoryInstance,
|
CreateMemoryInstance,
|
||||||
GetModuleSpecifications);
|
GetModuleSpecifications,
|
||||||
|
SaveCore);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -148,6 +151,14 @@ ObjectFilePECOFF::GetModuleSpecifications (const lldb_private::FileSpec& file,
|
||||||
return specs.GetSize() - initial_count;
|
return specs.GetSize() - initial_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ObjectFilePECOFF::SaveCore(const lldb::ProcessSP &process_sp,
|
||||||
|
const lldb_private::FileSpec &outfile,
|
||||||
|
lldb_private::Error &error)
|
||||||
|
{
|
||||||
|
return SaveMiniDump(process_sp, outfile, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ObjectFilePECOFF::MagicBytesMatch (DataBufferSP& data_sp)
|
ObjectFilePECOFF::MagicBytesMatch (DataBufferSP& data_sp)
|
||||||
|
|
|
@ -94,6 +94,11 @@ public:
|
||||||
lldb::offset_t length,
|
lldb::offset_t length,
|
||||||
lldb_private::ModuleSpecList &specs);
|
lldb_private::ModuleSpecList &specs);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
SaveCore (const lldb::ProcessSP &process_sp,
|
||||||
|
const lldb_private::FileSpec &outfile,
|
||||||
|
lldb_private::Error &error);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
MagicBytesMatch (lldb::DataBufferSP& data_sp);
|
MagicBytesMatch (lldb::DataBufferSP& data_sp);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
//===-- WindowsMiniDump.cpp -------------------------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// This function is separated out from ObjectFilePECOFF.cpp to name avoid name
|
||||||
|
// collisions with WinAPI preprocessor macros.
|
||||||
|
|
||||||
|
#include "WindowsMiniDump.h"
|
||||||
|
#include "lldb/Host/FileSpec.h"
|
||||||
|
#include "llvm/Support/ConvertUTF.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include "lldb/Host/windows/windows.h"
|
||||||
|
#include <DbgHelp.h> // for MiniDumpWriteDump
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace lldb_private {
|
||||||
|
|
||||||
|
bool
|
||||||
|
SaveMiniDump(const lldb::ProcessSP &process_sp,
|
||||||
|
const lldb_private::FileSpec &outfile,
|
||||||
|
lldb_private::Error &error)
|
||||||
|
{
|
||||||
|
if (!process_sp) return false;
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE process_handle = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, process_sp->GetID());
|
||||||
|
const std::string file_name = outfile.GetCString();
|
||||||
|
std::wstring wide_name;
|
||||||
|
wide_name.resize(file_name.size() + 1);
|
||||||
|
char * result_ptr = reinterpret_cast<char *>(&wide_name[0]);
|
||||||
|
const UTF8 *error_ptr = nullptr;
|
||||||
|
if (!llvm::ConvertUTF8toWide(sizeof(wchar_t), file_name, result_ptr, error_ptr)) {
|
||||||
|
error.SetErrorString("cannot convert file name");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
HANDLE file_handle = ::CreateFileW(wide_name.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
const auto result = ::MiniDumpWriteDump(process_handle, process_sp->GetID(), file_handle, MiniDumpNormal, NULL, NULL, NULL);
|
||||||
|
::CloseHandle(file_handle);
|
||||||
|
::CloseHandle(process_handle);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namesapce lldb_private
|
|
@ -0,0 +1,24 @@
|
||||||
|
//===-- WindowsMiniDump.h ---------------------------------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef liblldb_WindowsMiniDump_h_
|
||||||
|
#define liblldb_WindowsMiniDump_h_
|
||||||
|
|
||||||
|
#include "lldb/Target/Process.h"
|
||||||
|
|
||||||
|
namespace lldb_private {
|
||||||
|
|
||||||
|
bool
|
||||||
|
SaveMiniDump(const lldb::ProcessSP &process_sp,
|
||||||
|
const lldb_private::FileSpec &outfile,
|
||||||
|
lldb_private::Error &error);
|
||||||
|
|
||||||
|
} // namespace lldb_private
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue