forked from OSchip/llvm-project
parent
4d5d1dd6d5
commit
af75dab383
|
@ -341,6 +341,10 @@ public:
|
|||
bool
|
||||
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:
|
||||
friend class SBAddress;
|
||||
friend class SBBreakpoint;
|
||||
|
|
|
@ -180,6 +180,9 @@ public:
|
|||
bool stop_at_entry,
|
||||
lldb::SBError& error);
|
||||
|
||||
SBProcess
|
||||
LoadCore (const char *core_file);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Launch a new process with sensible defaults.
|
||||
///
|
||||
|
@ -214,9 +217,6 @@ public:
|
|||
SBProcess
|
||||
Launch (SBLaunchInfo &launch_info, SBError& error);
|
||||
|
||||
SBProcess
|
||||
LoadCore (const char *core_file);
|
||||
|
||||
SBProcess
|
||||
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
|
||||
IsInstrumentationRuntimePresent(lldb::InstrumentationRuntimeType type);
|
||||
|
||||
lldb::SBError
|
||||
SaveCore(const char *file_name);
|
||||
|
||||
%pythoncode %{
|
||||
def __get_is_alive__(self):
|
||||
'''Returns "True" if the process is currently alive, "False" otherwise'''
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "lldb/Core/Debugger.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/Core/State.h"
|
||||
#include "lldb/Core/Stream.h"
|
||||
#include "lldb/Core/StreamFile.h"
|
||||
|
@ -1425,3 +1426,27 @@ SBProcess::IsInstrumentationRuntimePresent(InstrumentationRuntimeType type)
|
|||
|
||||
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())
|
||||
{
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
add_lldb_library(lldbPluginObjectFilePECOFF
|
||||
ObjectFilePECOFF.cpp
|
||||
WindowsMiniDump.cpp
|
||||
)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ObjectFilePECOFF.h"
|
||||
#include "WindowsMiniDump.h"
|
||||
|
||||
#include "llvm/Support/COFF.h"
|
||||
|
||||
|
@ -24,6 +25,7 @@
|
|||
#include "lldb/Core/Timer.h"
|
||||
#include "lldb/Core/UUID.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
#include "lldb/Target/SectionLoadList.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
|
@ -42,7 +44,8 @@ ObjectFilePECOFF::Initialize()
|
|||
GetPluginDescriptionStatic(),
|
||||
CreateInstance,
|
||||
CreateMemoryInstance,
|
||||
GetModuleSpecifications);
|
||||
GetModuleSpecifications,
|
||||
SaveCore);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -148,6 +151,14 @@ ObjectFilePECOFF::GetModuleSpecifications (const lldb_private::FileSpec& file,
|
|||
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
|
||||
ObjectFilePECOFF::MagicBytesMatch (DataBufferSP& data_sp)
|
||||
|
|
|
@ -94,6 +94,11 @@ public:
|
|||
lldb::offset_t length,
|
||||
lldb_private::ModuleSpecList &specs);
|
||||
|
||||
static bool
|
||||
SaveCore (const lldb::ProcessSP &process_sp,
|
||||
const lldb_private::FileSpec &outfile,
|
||||
lldb_private::Error &error);
|
||||
|
||||
static bool
|
||||
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