summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2012-02-09 06:16:32 +0000
committerGreg Clayton <gclayton@apple.com>2012-02-09 06:16:32 +0000
commitc3776bf288a33cb42daac1a6583ddb5e581839d6 (patch)
tree510d067a8c55229aaf66014e0e93338065bdcb80
parent6c07547b568a1307d0a3279a0cfdf89365ae8444 (diff)
downloadbcm5719-llvm-c3776bf288a33cb42daac1a6583ddb5e581839d6.tar.gz
bcm5719-llvm-c3776bf288a33cb42daac1a6583ddb5e581839d6.zip
First pass at mach-o core file support is in. It currently works for x86_64
user space programs. The core file support is implemented by making a process plug-in that will dress up the threads and stack frames by using the core file memory. Added many default implementations for the lldb_private::Process functions so that plug-ins like the ProcessMachCore don't need to override many many functions only to have to return an error. Added new virtual functions to the ObjectFile class for extracting the frozen thread states that might be stored in object files. The default implementations return no thread information, but any platforms that support core files that contain frozen thread states (like mach-o) can make a module using the core file and then extract the information. The object files can enumerate the threads and also provide the register state for each thread. Since each object file knows how the thread registers are stored, they are responsible for creating a suitable register context that can be used by the core file threads. Changed the process CreateInstace callbacks to return a shared pointer and to also take an "const FileSpec *core_file" parameter to allow for core file support. This will also allow for lldb_private::Process subclasses to be made that could load crash logs. This should be possible on darwin where the crash logs contain all of the stack frames for all of the threads, yet the crash logs only contain the registers for the crashed thrad. It should also allow some variables to be viewed for the thread that crashed. llvm-svn: 150154
-rw-r--r--lldb/include/lldb/Core/RangeMap.h15
-rw-r--r--lldb/include/lldb/Symbol/ObjectFile.h19
-rw-r--r--lldb/include/lldb/Target/Process.h105
-rw-r--r--lldb/include/lldb/Target/Target.h4
-rw-r--r--lldb/include/lldb/Target/ThreadList.h2
-rw-r--r--lldb/include/lldb/lldb-private-interfaces.h2
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj24
-rw-r--r--lldb/source/API/SBTarget.cpp16
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp6
-rw-r--r--lldb/source/Commands/CommandObjectTarget.cpp53
-rw-r--r--lldb/source/Core/ModuleList.cpp27
-rw-r--r--lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp33
-rw-r--r--lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp162
-rw-r--r--lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h10
-rw-r--r--lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp2
-rw-r--r--lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp2
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp13
-rw-r--r--lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h13
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp27
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h6
-rw-r--r--lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp346
-rw-r--r--lldb/source/Plugins/Process/mach-core/ProcessMachCore.h147
-rw-r--r--lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp145
-rw-r--r--lldb/source/Plugins/Process/mach-core/ThreadMachCore.h98
-rw-r--r--lldb/source/Symbol/ObjectFile.cpp10
-rw-r--r--lldb/source/Target/Process.cpp51
-rw-r--r--lldb/source/Target/Target.cpp4
-rw-r--r--lldb/source/Target/ThreadList.cpp2
-rw-r--r--lldb/source/lldb.cpp4
30 files changed, 1263 insertions, 91 deletions
diff --git a/lldb/include/lldb/Core/RangeMap.h b/lldb/include/lldb/Core/RangeMap.h
index 1c858c54bef..dd41375499b 100644
--- a/lldb/include/lldb/Core/RangeMap.h
+++ b/lldb/include/lldb/Core/RangeMap.h
@@ -682,6 +682,21 @@ namespace lldb_private {
return NULL;
}
+ Entry *
+ Back()
+ {
+ if (!m_entries.empty())
+ return &m_entries.back();
+ return NULL;
+ }
+
+ const Entry *
+ Back() const
+ {
+ if (!m_entries.empty())
+ return &m_entries.back();
+ return NULL;
+ }
protected:
Collection m_entries;
diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h
index f35e63213ca..e17e9c7721d 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -415,6 +415,18 @@ public:
virtual lldb_private::Address
GetHeaderAddress () { return Address();}
+
+ virtual uint32_t
+ GetNumThreadContexts ()
+ {
+ return 0;
+ }
+
+ virtual lldb::RegisterContextSP
+ GetThreadContextAtIndex (uint32_t idx, lldb_private::Thread &thread)
+ {
+ return lldb::RegisterContextSP();
+ }
//------------------------------------------------------------------
/// The object file should be able to calculate its type by looking
/// at its file header and possibly the sections or other data in
@@ -504,8 +516,13 @@ protected:
DataExtractor m_data; ///< The data for this object file so things can be parsed lazily.
lldb_private::UnwindTable m_unwind_table; /// < Table of FuncUnwinders objects created for this ObjectFile's functions
lldb::ProcessWP m_process_wp;
- const bool m_in_memory;
+ const lldb::addr_t m_memory_addr;
+ bool
+ IsInMemory () const
+ {
+ return m_memory_addr != LLDB_INVALID_ADDRESS;
+ }
//------------------------------------------------------------------
/// Sets the architecture for a module. At present the architecture
/// can only be set if it is invalid. It is not allowed to switch from
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index f8e21bc1039..39857610850 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -1479,8 +1479,11 @@ public:
///
/// @see Process::CanDebug ()
//------------------------------------------------------------------
- static Process*
- FindPlugin (Target &target, const char *plugin_name, Listener &listener);
+ static lldb::ProcessSP
+ FindPlugin (Target &target,
+ const char *plugin_name,
+ Listener &listener,
+ const FileSpec *crash_file_path);
@@ -1588,6 +1591,17 @@ public:
virtual Error
Launch (const ProcessLaunchInfo &launch_info);
+ virtual Error
+ LoadCore ();
+
+ virtual Error
+ DoLoadCore ()
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support loading core files.", GetShortPluginName());
+ return error;
+ }
+
//------------------------------------------------------------------
/// Attach to an existing process using the process attach info.
///
@@ -1844,7 +1858,12 @@ public:
/// LLDB_INVALID_PROCESS_ID if attaching fails.
//------------------------------------------------------------------
virtual Error
- DoAttachToProcessWithID (lldb::pid_t pid) = 0;
+ DoAttachToProcessWithID (lldb::pid_t pid)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support attaching to a process by pid", GetShortPluginName());
+ return error;
+ }
//------------------------------------------------------------------
/// Attach to an existing process using a partial process name.
@@ -1940,7 +1959,13 @@ public:
//------------------------------------------------------------------
virtual Error
DoLaunch (Module *exe_module,
- const ProcessLaunchInfo &launch_info) = 0;
+ const ProcessLaunchInfo &launch_info)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support launching processes", GetShortPluginName());
+ return error;
+ }
+
//------------------------------------------------------------------
/// Called after launching a process.
@@ -1983,7 +2008,13 @@ public:
/// @see Thread:Suspend()
//------------------------------------------------------------------
virtual Error
- DoResume () = 0;
+ DoResume ()
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support resuming processes", GetShortPluginName());
+ return error;
+ }
+
//------------------------------------------------------------------
/// Called after resuming a process.
@@ -2026,7 +2057,13 @@ public:
/// otherwise.
//------------------------------------------------------------------
virtual Error
- DoHalt (bool &caused_stop) = 0;
+ DoHalt (bool &caused_stop)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support halting processes", GetShortPluginName());
+ return error;
+ }
+
//------------------------------------------------------------------
/// Called after halting a process.
@@ -2060,7 +2097,13 @@ public:
/// false otherwise.
//------------------------------------------------------------------
virtual Error
- DoDetach () = 0;
+ DoDetach ()
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support detaching from processes", GetShortPluginName());
+ return error;
+ }
+
//------------------------------------------------------------------
/// Called after detaching from a process.
@@ -2092,9 +2135,12 @@ public:
/// Returns an error object.
//------------------------------------------------------------------
virtual Error
- DoSignal (int signal) = 0;
-
-
+ DoSignal (int signal)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support senging signals to processes", GetShortPluginName());
+ return error;
+ }
virtual Error
WillDestroy () { return Error(); }
@@ -2115,7 +2161,6 @@ public:
virtual void
DidSignal () {}
-
//------------------------------------------------------------------
/// Currently called as part of ShouldStop.
/// FIXME: Should really happen when the target stops before the
@@ -2445,7 +2490,12 @@ public:
/// The number of bytes that were actually written.
//------------------------------------------------------------------
virtual size_t
- DoWriteMemory (lldb::addr_t vm_addr, const void *buf, size_t size, Error &error) = 0;
+ DoWriteMemory (lldb::addr_t vm_addr, const void *buf, size_t size, Error &error)
+ {
+ error.SetErrorStringWithFormat("error: %s does not support writing to processes", GetShortPluginName());
+ return 0;
+ }
+
//------------------------------------------------------------------
/// Write all or part of a scalar value to memory.
@@ -2537,7 +2587,12 @@ public:
//------------------------------------------------------------------
virtual lldb::addr_t
- DoAllocateMemory (size_t size, uint32_t permissions, Error &error) = 0;
+ DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
+ {
+ error.SetErrorStringWithFormat("error: %s does not support allocating in the debug process", GetShortPluginName());
+ return LLDB_INVALID_ADDRESS;
+ }
+
//------------------------------------------------------------------
/// The public interface to allocating memory in the process.
@@ -2660,7 +2715,13 @@ public:
//------------------------------------------------------------------
virtual Error
- DoDeallocateMemory (lldb::addr_t ptr) = 0;
+ DoDeallocateMemory (lldb::addr_t ptr)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support deallocating in the debug process", GetShortPluginName());
+ return error;
+ }
+
//------------------------------------------------------------------
/// The public interface to deallocating memory in the process.
@@ -2741,10 +2802,22 @@ public:
GetSoftwareBreakpointTrapOpcode (BreakpointSite* bp_site);
virtual Error
- EnableBreakpoint (BreakpointSite *bp_site) = 0;
+ EnableBreakpoint (BreakpointSite *bp_site)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support enabling breakpoints", GetShortPluginName());
+ return error;
+ }
+
virtual Error
- DisableBreakpoint (BreakpointSite *bp_site) = 0;
+ DisableBreakpoint (BreakpointSite *bp_site)
+ {
+ Error error;
+ error.SetErrorStringWithFormat("error: %s does not support disabling breakpoints", GetShortPluginName());
+ return error;
+ }
+
// This is implemented completely using the lldb::Process API. Subclasses
// don't need to implement this function unless the standard flow of
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 1c8afc2946c..5e51e4151ea 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -335,7 +335,9 @@ public:
Dump (Stream *s, lldb::DescriptionLevel description_level);
const lldb::ProcessSP &
- CreateProcess (Listener &listener, const char *plugin_name = NULL);
+ CreateProcess (Listener &listener,
+ const char *plugin_name,
+ const FileSpec *crash_file);
const lldb::ProcessSP &
GetProcessSP () const;
diff --git a/lldb/include/lldb/Target/ThreadList.h b/lldb/include/lldb/Target/ThreadList.h
index 3a998c49f85..be6a1a2d402 100644
--- a/lldb/include/lldb/Target/ThreadList.h
+++ b/lldb/include/lldb/Target/ThreadList.h
@@ -43,7 +43,7 @@ public:
GetSize(bool can_update = true);
void
- AddThread (lldb::ThreadSP &thread_sp);
+ AddThread (const lldb::ThreadSP &thread_sp);
// Return the selected thread if there is one. Otherwise, return the thread
// selected at index 0.
diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h
index 1e95c04a936..a74a7561c32 100644
--- a/lldb/include/lldb/lldb-private-interfaces.h
+++ b/lldb/include/lldb/lldb-private-interfaces.h
@@ -27,7 +27,7 @@ namespace lldb_private
typedef OperatingSystem* (*OperatingSystemCreateInstance) (Process *process, bool force);
typedef LanguageRuntime *(*LanguageRuntimeCreateInstance) (Process *process, lldb::LanguageType language);
typedef Platform* (*PlatformCreateInstance) ();
- typedef Process* (*ProcessCreateInstance) (Target &target, Listener &listener);
+ typedef lldb::ProcessSP (*ProcessCreateInstance) (Target &target, Listener &listener, const FileSpec *crash_file_path);
typedef SymbolFile* (*SymbolFileCreateInstance) (ObjectFile* obj_file);
typedef SymbolVendor* (*SymbolVendorCreateInstance) (Module *module); // Module can be NULL for default system symbol vendor
typedef bool (*BreakpointHitCallback) (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj
index 19fe67c0c83..a048430423c 100644
--- a/lldb/lldb.xcodeproj/project.pbxproj
+++ b/lldb/lldb.xcodeproj/project.pbxproj
@@ -334,6 +334,10 @@
26957D9A13D381C900670048 /* RegisterContextDarwin_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26957D9413D381C900670048 /* RegisterContextDarwin_i386.cpp */; };
26957D9C13D381C900670048 /* RegisterContextDarwin_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26957D9613D381C900670048 /* RegisterContextDarwin_x86_64.cpp */; };
2697A54D133A6305004E4240 /* PlatformDarwin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2697A54B133A6305004E4240 /* PlatformDarwin.cpp */; };
+ 26A527C114E24F5F00F3A14A /* ProcessMachCore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A527BD14E24F5F00F3A14A /* ProcessMachCore.cpp */; };
+ 26A527C214E24F5F00F3A14A /* ProcessMachCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 26A527BE14E24F5F00F3A14A /* ProcessMachCore.h */; };
+ 26A527C314E24F5F00F3A14A /* ThreadMachCore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A527BF14E24F5F00F3A14A /* ThreadMachCore.cpp */; };
+ 26A527C414E24F5F00F3A14A /* ThreadMachCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 26A527C014E24F5F00F3A14A /* ThreadMachCore.h */; };
26A69C5F137A17A500262477 /* RegisterValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C6886E137880C400407EDF /* RegisterValue.cpp */; };
26A7A035135E6E4200FB369E /* NamedOptionValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A7A034135E6E4200FB369E /* NamedOptionValue.cpp */; };
26B1FCB813381071002886E2 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */; };
@@ -778,6 +782,10 @@
26A3B4AC1181454800381BC2 /* ObjectContainerBSDArchive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectContainerBSDArchive.cpp; sourceTree = "<group>"; };
26A3B4AD1181454800381BC2 /* ObjectContainerBSDArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectContainerBSDArchive.h; sourceTree = "<group>"; };
26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = LLDBWrapPython.cpp; path = source/LLDBWrapPython.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
+ 26A527BD14E24F5F00F3A14A /* ProcessMachCore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessMachCore.cpp; sourceTree = "<group>"; };
+ 26A527BE14E24F5F00F3A14A /* ProcessMachCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessMachCore.h; sourceTree = "<group>"; };
+ 26A527BF14E24F5F00F3A14A /* ThreadMachCore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadMachCore.cpp; sourceTree = "<group>"; };
+ 26A527C014E24F5F00F3A14A /* ThreadMachCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadMachCore.h; sourceTree = "<group>"; };
26A7A034135E6E4200FB369E /* NamedOptionValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NamedOptionValue.cpp; path = source/Interpreter/NamedOptionValue.cpp; sourceTree = "<group>"; };
26A7A036135E6E5300FB369E /* NamedOptionValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NamedOptionValue.h; path = include/lldb/Interpreter/NamedOptionValue.h; sourceTree = "<group>"; };
26B167A41123BF5500DC7B4F /* ThreadSafeValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSafeValue.h; path = include/lldb/Core/ThreadSafeValue.h; sourceTree = "<group>"; };
@@ -1573,6 +1581,7 @@
children = (
4CEE62F71145F1C70064CF93 /* GDB Remote */,
2642FBA713D003B400ED6808 /* MacOSX-Kernel */,
+ 26A527BC14E24F5F00F3A14A /* mach-core */,
26B4666E11A2080F00CF6220 /* Utility */,
);
path = Process;
@@ -1977,6 +1986,17 @@
path = "BSD-Archive";
sourceTree = "<group>";
};
+ 26A527BC14E24F5F00F3A14A /* mach-core */ = {
+ isa = PBXGroup;
+ children = (
+ 26A527BD14E24F5F00F3A14A /* ProcessMachCore.cpp */,
+ 26A527BE14E24F5F00F3A14A /* ProcessMachCore.h */,
+ 26A527BF14E24F5F00F3A14A /* ThreadMachCore.cpp */,
+ 26A527C014E24F5F00F3A14A /* ThreadMachCore.h */,
+ );
+ path = "mach-core";
+ sourceTree = "<group>";
+ };
26AC3F441365F40E0065C7EF /* UnwindAssembly */ = {
isa = PBXGroup;
children = (
@@ -2871,6 +2891,8 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ 26A527C214E24F5F00F3A14A /* ProcessMachCore.h in Headers */,
+ 26A527C414E24F5F00F3A14A /* ThreadMachCore.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -3530,6 +3552,8 @@
494260DA14579144003C1C78 /* VerifyDecl.cpp in Sources */,
49DA65031485C92A005FF180 /* AppleObjCSymbolVendor.cpp in Sources */,
4966DCC4148978A10028481B /* ClangExternalASTSourceCommon.cpp in Sources */,
+ 26A527C114E24F5F00F3A14A /* ProcessMachCore.cpp in Sources */,
+ 26A527C314E24F5F00F3A14A /* ThreadMachCore.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 5988887c551..75f2e7a78d1 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -225,9 +225,9 @@ SBTarget::Launch
else
{
if (listener.IsValid())
- process_sp = target_sp->CreateProcess (listener.ref());
+ process_sp = target_sp->CreateProcess (listener.ref(), NULL, NULL);
else
- process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener());
+ process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL);
}
if (process_sp)
@@ -346,9 +346,9 @@ SBTarget::AttachToProcessWithID
else
{
if (listener.IsValid())
- process_sp = target_sp->CreateProcess (listener.ref());
+ process_sp = target_sp->CreateProcess (listener.ref(), NULL, NULL);
else
- process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener());
+ process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL);
}
if (process_sp)
{
@@ -421,9 +421,9 @@ SBTarget::AttachToProcessWithName
else
{
if (listener.IsValid())
- process_sp = target_sp->CreateProcess (listener.ref());
+ process_sp = target_sp->CreateProcess (listener.ref(), NULL, NULL);
else
- process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener());
+ process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), NULL, NULL);
}
if (process_sp)
@@ -467,9 +467,9 @@ SBTarget::ConnectRemote
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
if (listener.IsValid())
- process_sp = target_sp->CreateProcess (listener.ref(), plugin_name);
+ process_sp = target_sp->CreateProcess (listener.ref(), plugin_name, NULL);
else
- process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), plugin_name);
+ process_sp = target_sp->CreateProcess (target_sp->GetDebugger().GetListener(), plugin_name, NULL);
if (process_sp)
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index fb40d2c8ddd..d9070a31ce5 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -189,7 +189,7 @@ public:
else
{
const char *plugin_name = m_options.launch_info.GetProcessPluginName();
- process = target->CreateProcess (debugger.GetListener(), plugin_name).get();
+ process = target->CreateProcess (debugger.GetListener(), plugin_name, NULL).get();
if (process)
error = process->Launch (m_options.launch_info);
}
@@ -501,7 +501,7 @@ public:
if (state != eStateConnected)
{
const char *plugin_name = m_options.attach_info.GetProcessPluginName();
- process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
+ process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get();
}
if (process)
@@ -870,7 +870,7 @@ public:
plugin_name = m_options.plugin_name.c_str();
const char *remote_url = command.GetArgumentAtIndex(0);
- process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
+ process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get();
if (process)
{
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 12622b5b1f7..a31a8ec3e2e 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -148,7 +148,8 @@ public:
NULL),
m_option_group (interpreter),
m_arch_option (),
- m_platform_options(true) // Do include the "--platform" option in the platform settings by passing true
+ m_platform_options(true), // Do include the "--platform" option in the platform settings by passing true
+ m_core_file (LLDB_OPT_SET_1, false, "core-file", 'c', 0, eArgTypePath, "Fullpath to a core file to use for this target.")
{
CommandArgumentEntry arg;
CommandArgumentData file_arg;
@@ -165,6 +166,7 @@ public:
m_option_group.Append (&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ m_option_group.Append (&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Finalize();
}
@@ -182,11 +184,16 @@ public:
Execute (Args& command, CommandReturnObject &result)
{
const int argc = command.GetArgumentCount();
- if (argc == 1)
+ FileSpec core_file (m_core_file.GetOptionValue().GetCurrentValue());
+
+ if (argc == 1 || core_file)
{
const char *file_path = command.GetArgumentAtIndex(0);
Timer scoped_timer(__PRETTY_FUNCTION__, "(lldb) target create '%s'", file_path);
- FileSpec file_spec (file_path, true);
+ FileSpec file_spec;
+
+ if (file_path)
+ file_spec.SetFile (file_path, true);
TargetSP target_sp;
Debugger &debugger = m_interpreter.GetDebugger();
@@ -202,8 +209,41 @@ public:
if (target_sp)
{
debugger.GetTargetList().SetSelectedTarget(target_sp.get());
- result.AppendMessageWithFormat ("Current executable set to '%s' (%s).\n", file_path, target_sp->GetArchitecture().GetArchitectureName());
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ if (core_file)
+ {
+ ProcessSP process_sp (target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), NULL, &core_file));
+ char core_path[PATH_MAX];
+ core_file.GetPath(core_path, sizeof(core_path));
+
+ if (process_sp)
+ {
+ // Seems wierd that we Launch a core file, but that is
+ // what we do!
+ error = process_sp->LoadCore();
+
+ if (error.Fail())
+ {
+ result.AppendError(error.AsCString("can't find plug-in for core file"));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ result.AppendMessageWithFormat ("Core file '%s' (%s) was loaded.\n", core_path, target_sp->GetArchitecture().GetArchitectureName());
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Unable to find process plug-in for core file '%s'\n", core_path);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendMessageWithFormat ("Current executable set to '%s' (%s).\n", file_path, target_sp->GetArchitecture().GetArchitectureName());
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
}
else
{
@@ -213,7 +253,7 @@ public:
}
else
{
- result.AppendErrorWithFormat("'%s' takes exactly one executable path argument.\n", m_cmd_name.c_str());
+ result.AppendErrorWithFormat("'%s' takes exactly one executable path argument, or use the --core-file option.\n", m_cmd_name.c_str());
result.SetStatus (eReturnStatusFailed);
}
return result.Succeeded();
@@ -247,6 +287,7 @@ private:
OptionGroupOptions m_option_group;
OptionGroupArchitecture m_arch_option;
OptionGroupPlatform m_platform_options;
+ OptionGroupFile m_core_file;
};
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index 0b400075c1a..8f372c51727 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -803,20 +803,25 @@ ModuleList::GetSharedModule
// Make sure there are a module and an object file since we can specify
// a valid file path with an architecture that might not be in that file.
// By getting the object file we can guarantee that the architecture matches
- if (module_sp && module_sp->GetObjectFile())
+ if (module_sp)
{
- // If we get in here we got the correct arch, now we just need
- // to verify the UUID if one was given
- if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
- module_sp.reset();
- else
+ if (module_sp->GetObjectFile())
{
- if (did_create_ptr)
- *did_create_ptr = true;
-
- shared_module_list.Append(module_sp);
- return error;
+ // If we get in here we got the correct arch, now we just need
+ // to verify the UUID if one was given
+ if (uuid_ptr && *uuid_ptr != module_sp->GetUUID())
+ module_sp.reset();
+ else
+ {
+ if (did_create_ptr)
+ *did_create_ptr = true;
+
+ shared_module_list.Append(module_sp);
+ return error;
+ }
}
+ else
+ module_sp.reset();
}
}
}
diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
index f082093e690..d6094b439ab 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
@@ -7,6 +7,9 @@
//
//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/MachO.h"
+
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/DataBufferHeap.h"
@@ -211,7 +214,35 @@ bool
DynamicLoaderMacOSXDYLD::LocateDYLD()
{
if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS)
- m_dyld_all_image_infos_addr = m_process->GetImageInfoAddress ();
+ {
+ // Check the image info addr as it might point to the
+ // mach header for dyld, or it might point to the
+ // dyld_all_image_infos struct
+ addr_t shlib_addr = m_process->GetImageInfoAddress ();
+
+ ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder();
+ uint8_t buf[4];
+ DataExtractor data (buf, sizeof(buf), byte_order, 4);
+ Error error;
+ if (m_process->ReadMemory (shlib_addr, buf, 4, error) == 4)
+ {
+ uint32_t offset = 0;
+ uint32_t magic = data.GetU32 (&offset);
+ switch (magic)
+ {
+ case llvm::MachO::HeaderMagic32:
+ case llvm::MachO::HeaderMagic64:
+ case llvm::MachO::HeaderMagic32Swapped:
+ case llvm::MachO::HeaderMagic64Swapped:
+ return ReadDYLDInfoFromMemoryAndSetNotificationCallback(shlib_addr);
+
+ default:
+ break;
+ }
+ }
+ // Maybe it points to the all image infos?
+ m_dyld_all_image_infos_addr = shlib_addr;
+ }
if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS)
{
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 67773e7b2c8..67fe1e4e66f 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -27,12 +27,110 @@
#include "lldb/Symbol/ClangNamespaceDecl.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
+#include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h"
using namespace lldb;
using namespace lldb_private;
using namespace llvm::MachO;
+class RegisterContextDarwin_x86_64_Mach : public RegisterContextDarwin_x86_64
+{
+public:
+ RegisterContextDarwin_x86_64_Mach (lldb_private::Thread &thread, const DataExtractor &data) :
+ RegisterContextDarwin_x86_64 (thread, 0)
+ {
+ SetRegisterDataFrom_LC_THREAD (data);
+ }
+
+ virtual void
+ InvalidateAllRegisters ()
+ {
+ // Do nothing... registers are always valid...
+ }
+
+ void
+ SetRegisterDataFrom_LC_THREAD (const DataExtractor &data)
+ {
+ int flavor;
+ uint32_t offset = 0;
+ SetError (GPRRegSet, Read, -1);
+ SetError (FPURegSet, Read, -1);
+ SetError (EXCRegSet, Read, -1);
+ while ((flavor = data.GetU32 (&offset)) > 0)
+ {
+ uint32_t i;
+ uint32_t count = data.GetU32 (&offset);
+ switch (flavor)
+ {
+ case 7:
+ case 8:
+ case 9:
+ // Goofy extra flavor inside state...
+ flavor = data.GetU32 (&offset);
+ count = data.GetU32 (&offset);
+ default:
+ break;
+ }
+
+ switch (flavor)
+ {
+ case GPRRegSet:
+ for (i=0; i<count; ++i)
+ (&gpr.rax)[i] = data.GetU64(&offset);
+ SetError (GPRRegSet, Read, 0);
+ break;
+ case FPURegSet:
+ // TODO: fill in FPU regs....
+ //SetError (FPURegSet, Read, -1);
+ break;
+ case EXCRegSet:
+ exc.trapno = data.GetU32(&offset);
+ exc.err = data.GetU32(&offset);
+ exc.faultvaddr = data.GetU64(&offset);
+ SetError (EXCRegSet, Read, 0);
+ break;
+ }
+ }
+ }
+protected:
+ virtual int
+ DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
+ {
+ return 0;
+ }
+
+ virtual int
+ DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
+ {
+ return 0;
+ }
+
+ virtual int
+ DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
+ {
+ return 0;
+ }
+
+ virtual int
+ DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
+ {
+ return 0;
+ }
+
+ virtual int
+ DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
+ {
+ return 0;
+ }
+
+ virtual int
+ DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
+ {
+ return 0;
+ }
+};
+
#define MACHO_NLIST_ARM_SYMBOL_IS_THUMB 0x0008
void
@@ -166,10 +264,13 @@ ObjectFileMachO::MagicBytesMatch (DataBufferSP& data_sp,
ObjectFileMachO::ObjectFileMachO(Module* module, DataBufferSP& data_sp, const FileSpec* file, addr_t offset, addr_t length) :
ObjectFile(module, file, offset, length, data_sp),
m_mutex (Mutex::eMutexTypeRecursive),
- m_header(),
m_sections_ap(),
m_symtab_ap(),
- m_entry_point_address ()
+ m_mach_segments(),
+ m_mach_sections(),
+ m_entry_point_address(),
+ m_thread_context_offsets(),
+ m_thread_context_offsets_valid(false)
{
::memset (&m_header, 0, sizeof(m_header));
::memset (&m_dysymtab, 0, sizeof(m_dysymtab));
@@ -181,10 +282,13 @@ ObjectFileMachO::ObjectFileMachO (lldb_private::Module* module,
lldb::addr_t header_addr) :
ObjectFile(module, process_sp, header_addr, header_data_sp),
m_mutex (Mutex::eMutexTypeRecursive),
- m_header(),
m_sections_ap(),
m_symtab_ap(),
- m_entry_point_address ()
+ m_mach_segments(),
+ m_mach_sections(),
+ m_entry_point_address(),
+ m_thread_context_offsets(),
+ m_thread_context_offsets_valid(false)
{
::memset (&m_header, 0, sizeof(m_header));
::memset (&m_dysymtab, 0, sizeof(m_dysymtab));
@@ -439,6 +543,7 @@ ObjectFileMachO::ParseSections ()
struct segment_command_64 load_cmd;
uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
uint32_t i;
+ const bool is_core = GetType() == eTypeCoreFile;
//bool dump_sections = false;
for (i=0; i<m_header.ncmds; ++i)
{
@@ -467,7 +572,7 @@ ObjectFileMachO::ParseSections ()
// Use a segment ID of the segment index shifted left by 8 so they
// never conflict with any of the sections.
SectionSP segment_sp;
- if (segment_name)
+ if (segment_name || is_core)
{
segment_sp.reset(new Section (NULL,
GetModule(), // Module to which this section belongs
@@ -1962,6 +2067,53 @@ ObjectFileMachO::GetHeaderAddress ()
return header_addr;
}
+uint32_t
+ObjectFileMachO::GetNumThreadContexts ()
+{
+ lldb_private::Mutex::Locker locker(m_mutex);
+ if (!m_thread_context_offsets_valid)
+ {
+ m_thread_context_offsets_valid = true;
+ uint32_t offset = MachHeaderSizeFromMagic(m_header.magic);
+ FileRangeArray::Entry file_range;
+ thread_command thread_cmd;
+ for (uint32_t i=0; i<m_header.ncmds; ++i)
+ {
+ const uint32_t cmd_offset = offset;
+ if (m_data.GetU32(&offset, &thread_cmd, 2) == NULL)
+ break;
+
+ if (thread_cmd.cmd == LoadCommandThread)
+ {
+ file_range.SetRangeBase (offset);
+ file_range.SetByteSize (thread_cmd.cmdsize - 8);
+ m_thread_context_offsets.Append (file_range);
+ }
+ offset = cmd_offset + thread_cmd.cmdsize;
+ }
+ }
+ return m_thread_context_offsets.GetSize();
+}
+
+lldb::RegisterContextSP
+ObjectFileMachO::GetThreadContextAtIndex (uint32_t idx, lldb_private::Thread &thread)
+{
+ lldb_private::Mutex::Locker locker(m_mutex);
+ if (!m_thread_context_offsets_valid)
+ GetNumThreadContexts ();
+
+ lldb::RegisterContextSP reg_ctx_sp;
+ const FileRangeArray::Entry *thread_context_file_range = m_thread_context_offsets.GetEntryAtIndex (idx);
+ if (thread_context_file_range)
+ {
+ DataExtractor data (m_data,
+ thread_context_file_range->GetRangeBase(),
+ thread_context_file_range->GetByteSize());
+ reg_ctx_sp.reset (new RegisterContextDarwin_x86_64_Mach (thread, data));
+ }
+ return reg_ctx_sp;
+}
+
ObjectFile::Type
ObjectFileMachO::CalculateType()
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
index 98c33ca1c5a..918b9216179 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -13,6 +13,7 @@
#include "llvm/Support/MachO.h"
#include "lldb/Core/Address.h"
+#include "lldb/Core/RangeMap.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -126,6 +127,12 @@ public:
virtual lldb_private::Address
GetHeaderAddress ();
+ virtual uint32_t
+ GetNumThreadContexts ();
+
+ virtual lldb::RegisterContextSP
+ GetThreadContextAtIndex (uint32_t idx, lldb_private::Thread &thread);
+
virtual ObjectFile::Type
CalculateType();
@@ -146,7 +153,10 @@ protected:
llvm::MachO::dysymtab_command m_dysymtab;
std::vector<llvm::MachO::segment_command_64> m_mach_segments;
std::vector<llvm::MachO::section_64> m_mach_sections;
+ typedef lldb_private::RangeArray<uint32_t, uint32_t, 1> FileRangeArray;
lldb_private::Address m_entry_point_address;
+ FileRangeArray m_thread_context_offsets;
+ bool m_thread_context_offsets_valid;
size_t
ParseSections ();
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index 8e139690964..9c8ca825c70 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -447,7 +447,7 @@ PlatformDarwin::Attach (ProcessAttachInfo &attach_info,
{
debugger.GetTargetList().SetSelectedTarget(target);
- process_sp = target->CreateProcess (listener, attach_info.GetProcessPluginName());
+ process_sp = target->CreateProcess (listener, attach_info.GetProcessPluginName(), NULL);
if (process_sp)
error = process_sp->Attach (attach_info);
diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 387737b7ab6..7114ac5a8e1 100644
--- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -378,7 +378,7 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
// The darwin always currently uses the GDB remote debugger plug-in
// so even when debugging locally we are debugging remotely!
- process_sp = target->CreateProcess (listener, "gdb-remote");
+ process_sp = target->CreateProcess (listener, "gdb-remote", NULL);
if (process_sp)
{
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index 8f327d6220d..119ffcc717d 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -49,10 +49,15 @@ ProcessKDP::Terminate()
}
-Process*
-ProcessKDP::CreateInstance (Target &target, Listener &listener)
-{
- return new ProcessKDP (target, listener);
+lldb::ProcessSP
+ProcessKDP::CreateInstance (Target &target,
+ Listener &listener,
+ const FileSpec *crash_file_path)
+{
+ lldb::ProcessSP process_sp;
+ if (crash_file_path == NULL)
+ process_sp.reset(new ProcessKDP (target, listener));
+ return process_sp;
}
bool
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
index 7ecd2fffef7..5b44637d785 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
@@ -38,8 +38,10 @@ public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- static Process*
- CreateInstance (lldb_private::Target& target, lldb_private::Listener &listener);
+ static lldb::ProcessSP
+ CreateInstance (lldb_private::Target& target,
+ lldb_private::Listener &listener,
+ const lldb_private::FileSpec *crash_file_path);
static void
Initialize();
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
index b2ed0859092..8160cd0cc0a 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
@@ -21,7 +21,7 @@ class RegisterContextDarwin_x86_64 : public lldb_private::RegisterContext
{
public:
RegisterContextDarwin_x86_64 (lldb_private::Thread &thread,
- uint32_t concrete_frame_idx);
+ uint32_t concrete_frame_idx);
virtual
~RegisterContextDarwin_x86_64();
@@ -239,36 +239,35 @@ protected:
return -1;
}
- int
+ virtual int
DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
{
return -1;
}
- int
+ virtual int
DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
{
return -1;
}
- int
+ virtual int
DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
{
return -1;
}
- int
+ virtual int
DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
{
return -1;
}
- int
+ virtual int
DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
{
return -1;
}
-
int
ReadRegisterSet (uint32_t set, bool force);
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 2e59bc0d6fa..afafaafaa06 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -94,10 +94,13 @@ ProcessGDBRemote::Terminate()
}
-Process*
-ProcessGDBRemote::CreateInstance (Target &target, Listener &listener)
+lldb::ProcessSP
+ProcessGDBRemote::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file_path)
{
- return new ProcessGDBRemote (target, listener);
+ lldb::ProcessSP process_sp;
+ if (crash_file_path == NULL)
+ process_sp.reset (new ProcessGDBRemote (target, listener));
+ return process_sp;
}
bool
@@ -109,7 +112,25 @@ ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name)
// For now we are just making sure the file exists for a given module
Module *exe_module = target.GetExecutableModulePointer();
if (exe_module)
+ {
+ ObjectFile *exe_objfile = exe_module->GetObjectFile();
+ // We can't debug core files...
+ switch (exe_objfile->GetType())
+ {
+ case ObjectFile::eTypeInvalid:
+ case ObjectFile::eTypeCoreFile:
+ case ObjectFile::eTypeDebugInfo:
+ case ObjectFile::eTypeObjectFile:
+ case ObjectFile::eTypeSharedLibrary:
+ case ObjectFile::eTypeStubLibrary:
+ return false;
+ case ObjectFile::eTypeExecutable:
+ case ObjectFile::eTypeDynamicLinker:
+ case ObjectFile::eTypeUnknown:
+ break;
+ }
return exe_module->GetFileSpec().Exists();
+ }
// However, if there is no executable module, we return true since we might be preparing to attach.
return true;
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 5688118a423..894aae2632c 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -39,8 +39,10 @@ public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- static Process*
- CreateInstance (lldb_private::Target& target, lldb_private::Listener &listener);
+ static lldb::ProcessSP
+ CreateInstance (lldb_private::Target& target,
+ lldb_private::Listener &listener,
+ const lldb_private::FileSpec *crash_file_path);
static void
Initialize();
diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
new file mode 100644
index 00000000000..9bfc0ff2e00
--- /dev/null
+++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.cpp
@@ -0,0 +1,346 @@
+//===-- ProcessMachCore.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <errno.h>
+#include <stdlib.h>
+
+// C++ Includes
+#include "llvm/Support/MachO.h"
+
+// Other libraries and framework includes
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+// Project includes
+#include "ProcessMachCore.h"
+#include "ThreadMachCore.h"
+#include "StopInfoMachException.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+const char *
+ProcessMachCore::GetPluginNameStatic()
+{
+ return "mach-o-core";
+}
+
+const char *
+ProcessMachCore::GetPluginDescriptionStatic()
+{
+ return "Mach-O core file debugging plug-in.";
+}
+
+void
+ProcessMachCore::Terminate()
+{
+ PluginManager::UnregisterPlugin (ProcessMachCore::CreateInstance);
+}
+
+
+lldb::ProcessSP
+ProcessMachCore::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file)
+{
+ lldb::ProcessSP process_sp;
+ if (crash_file)
+ process_sp.reset(new ProcessMachCore (target, listener, *crash_file));
+ return process_sp;
+}
+
+bool
+ProcessMachCore::CanDebug(Target &target, bool plugin_specified_by_name)
+{
+ if (plugin_specified_by_name)
+ return true;
+
+ // For now we are just making sure the file exists for a given module
+ if (!m_core_module_sp && m_core_file.Exists())
+ {
+ Error error (ModuleList::GetSharedModule(m_core_file, target.GetArchitecture(), NULL, NULL, 0, m_core_module_sp, NULL, NULL));
+
+ if (m_core_module_sp)
+ {
+ const llvm::Triple &triple_ref = m_core_module_sp->GetArchitecture().GetTriple();
+ if (triple_ref.getOS() == llvm::Triple::Darwin &&
+ triple_ref.getVendor() == llvm::Triple::Apple)
+ {
+ ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
+ if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+//----------------------------------------------------------------------
+// ProcessMachCore constructor
+//----------------------------------------------------------------------
+ProcessMachCore::ProcessMachCore(Target& target, Listener &listener, const FileSpec &core_file) :
+ Process (target, listener),
+ m_core_aranges (),
+ m_core_module_sp (),
+ m_core_file (core_file),
+ m_shlib_addr (LLDB_INVALID_ADDRESS)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ProcessMachCore::~ProcessMachCore()
+{
+ Clear();
+ // We need to call finalize on the process before destroying ourselves
+ // to make sure all of the broadcaster cleanup goes as planned. If we
+ // destruct this class, then Process::~Process() might have problems
+ // trying to fully destroy the broadcaster.
+ Finalize();
+}
+
+//----------------------------------------------------------------------
+// PluginInterface
+//----------------------------------------------------------------------
+const char *
+ProcessMachCore::GetPluginName()
+{
+ return "Process debugging plug-in that loads mach-o core files.";
+}
+
+const char *
+ProcessMachCore::GetShortPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ProcessMachCore::GetPluginVersion()
+{
+ return 1;
+}
+
+//----------------------------------------------------------------------
+// Process Control
+//----------------------------------------------------------------------
+Error
+ProcessMachCore::DoLoadCore ()
+{
+ Error error;
+ DataExtractor data;
+ ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
+ if (core_objfile == NULL)
+ {
+ error.SetErrorString ("invalid core object file");
+ return error;
+ }
+ SectionList *section_list = core_objfile->GetSectionList();
+ if (section_list == NULL)
+ {
+ error.SetErrorString ("core file has no sections");
+ return error;
+ }
+
+ const uint32_t num_sections = section_list->GetNumSections(0);
+ if (num_sections == 0)
+ {
+ error.SetErrorString ("core file has no sections");
+ return error;
+ }
+ bool ranges_are_sorted = true;
+ addr_t vm_addr = 0;
+ for (uint32_t i=0; i<num_sections; ++i)
+ {
+ Section *section = section_list->GetSectionAtIndex (i).get();
+ if (section)
+ {
+ lldb::addr_t section_vm_addr = section->GetFileAddress();
+
+ if (m_shlib_addr == LLDB_INVALID_ADDRESS)
+ {
+ if (core_objfile->ReadSectionData (section, data))
+ {
+ uint32_t offset = 0;
+ llvm::MachO::mach_header header;
+ if (data.GetU32(&offset, &header, sizeof(header)/sizeof(uint32_t)))
+ {
+
+ if (header.magic == llvm::MachO::HeaderMagic32 ||
+ header.magic == llvm::MachO::HeaderMagic64)
+ {
+ // Check MH_EXECUTABLE to see if we can find the mach image
+ // that contains the shared library list. The dynamic loader
+ // (dyld) is what contains the list for user applications,
+ // and the mach kernel contains a global that has the list
+ // of kexts to load
+ switch (header.filetype)
+ {
+ case llvm::MachO::HeaderFileTypeDynamicLinkEditor:
+ // Address of dyld "struct mach_header" in the core file
+ m_shlib_addr = section_vm_addr;
+ break;
+ case llvm::MachO::HeaderFileTypeExecutable:
+ // Check MH_EXECUTABLE file types to see if the dynamic link object flag
+ // is NOT set. If it isn't, then we have a mach_kernel.
+ if ((header.flags & llvm::MachO::HeaderFlagBitIsDynamicLinkObject) == 0)
+ {
+ // Address of the mach kernel "struct mach_header" in the core file.
+ m_shlib_addr = section_vm_addr;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ FileRange file_range (section->GetFileOffset(), section->GetFileSize());
+ VMRangeToFileOffset::Entry range_entry (section_vm_addr,
+ section->GetByteSize(),
+ file_range);
+
+ if (vm_addr > section_vm_addr)
+ ranges_are_sorted = false;
+ vm_addr = section->GetFileAddress();
+ VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
+ if (last_entry &&
+ last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
+ last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
+ {
+ last_entry->SetRangeEnd (range_entry.GetRangeEnd());
+ last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
+ }
+ else
+ {
+ m_core_aranges.Append(range_entry);
+ }
+ }
+ }
+ if (!ranges_are_sorted)
+ {
+ m_core_aranges.Sort();
+ }
+ if (!m_target.GetArchitecture().IsValid())
+ m_target.SetArchitecture(m_core_module_sp->GetArchitecture());
+
+ return error;
+}
+
+
+uint32_t
+ProcessMachCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
+{
+ if (old_thread_list.GetSize(false) == 0)
+ {
+ // Make up the thread the first time this is called so we can setup our one and only
+ // core thread state.
+ ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
+
+ if (core_objfile)
+ {
+ const uint32_t num_threads = core_objfile->GetNumThreadContexts ();
+ for (lldb::tid_t tid = 0; tid < num_threads; ++tid)
+ {
+ ThreadSP thread_sp(new ThreadMachCore (*this, tid));
+ new_thread_list.AddThread (thread_sp);
+ }
+ }
+ }
+ else
+ {
+ const uint32_t num_threads = old_thread_list.GetSize(false);
+ for (uint32_t i=0; i<num_threads; ++i)
+ new_thread_list.AddThread (old_thread_list.GetThreadAtIndex (i));
+ }
+ return new_thread_list.GetSize(false);
+}
+
+void
+ProcessMachCore::RefreshStateAfterStop ()
+{
+ // Let all threads recover from stopping and do any clean up based
+ // on the previous thread state (if any).
+ m_thread_list.RefreshStateAfterStop();
+ //SetThreadStopInfo (m_last_stop_packet);
+}
+
+Error
+ProcessMachCore::DoDestroy ()
+{
+ return Error();
+}
+
+//------------------------------------------------------------------
+// Process Queries
+//------------------------------------------------------------------
+
+bool
+ProcessMachCore::IsAlive ()
+{
+ return true;
+}
+
+//------------------------------------------------------------------
+// Process Memory
+//------------------------------------------------------------------
+size_t
+ProcessMachCore::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
+{
+ ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
+
+ if (core_objfile)
+ {
+ const VMRangeToFileOffset::Entry *core_memory_entry = m_core_aranges.FindEntryThatContains (addr);
+ if (core_memory_entry)
+ {
+ const addr_t offset = addr - core_memory_entry->GetRangeBase();
+ const addr_t bytes_left = core_memory_entry->GetRangeEnd() - addr;
+ size_t bytes_to_read = size;
+ if (bytes_to_read > bytes_left)
+ bytes_to_read = bytes_left;
+ return core_objfile->CopyData (core_memory_entry->data.GetRangeBase() + offset, bytes_to_read, buf);
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("core file does not contain 0x%llx", addr);
+ }
+ }
+ return 0;
+}
+
+void
+ProcessMachCore::Clear()
+{
+ m_thread_list.Clear();
+}
+
+void
+ProcessMachCore::Initialize()
+{
+ static bool g_initialized = false;
+
+ if (g_initialized == false)
+ {
+ g_initialized = true;
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ CreateInstance);
+ }
+}
+
+addr_t
+ProcessMachCore::GetImageInfoAddress()
+{
+ return m_shlib_addr;
+}
+
+
diff --git a/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h
new file mode 100644
index 00000000000..dfdf7f04cc2
--- /dev/null
+++ b/lldb/source/Plugins/Process/mach-core/ProcessMachCore.h
@@ -0,0 +1,147 @@
+//===-- ProcessMachCore.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_ProcessMachCore_h_
+#define liblldb_ProcessMachCore_h_
+
+// C Includes
+
+// C++ Includes
+#include <list>
+#include <vector>
+
+// Other libraries and framework includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Core/ThreadSafeValue.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+#include "CommunicationKDP.h"
+#include "Utility/StringExtractor.h"
+
+class ThreadKDP;
+
+class ProcessMachCore : public lldb_private::Process
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ static lldb::ProcessSP
+ CreateInstance (lldb_private::Target& target,
+ lldb_private::Listener &listener,
+ const lldb_private::FileSpec *crash_file_path);
+
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static const char *
+ GetPluginNameStatic();
+
+ static const char *
+ GetPluginDescriptionStatic();
+
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ ProcessMachCore(lldb_private::Target& target,
+ lldb_private::Listener &listener,
+ const lldb_private::FileSpec &core_file);
+
+ virtual
+ ~ProcessMachCore();
+
+ //------------------------------------------------------------------
+ // Check if a given Process
+ //------------------------------------------------------------------
+ virtual bool
+ CanDebug (lldb_private::Target &target,
+ bool plugin_specified_by_name);
+
+ //------------------------------------------------------------------
+ // Creating a new process, or attaching to an existing one
+ //------------------------------------------------------------------
+ virtual lldb_private::Error
+ DoLoadCore ();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ virtual const char *
+ GetPluginName();
+
+ virtual const char *
+ GetShortPluginName();
+
+ virtual uint32_t
+ GetPluginVersion();
+
+ //------------------------------------------------------------------
+ // Process Control
+ //------------------------------------------------------------------
+ virtual lldb_private::Error
+ DoDestroy ();
+
+ virtual void
+ RefreshStateAfterStop();
+
+ //------------------------------------------------------------------
+ // Process Queries
+ //------------------------------------------------------------------
+ virtual bool
+ IsAlive ();
+
+ //------------------------------------------------------------------
+ // Process Memory
+ //------------------------------------------------------------------
+ virtual size_t
+ DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
+
+ virtual lldb::addr_t
+ GetImageInfoAddress ();
+
+protected:
+ friend class ThreadMachCore;
+
+ void
+ Clear ( );
+
+ uint32_t
+ UpdateThreadList (lldb_private::ThreadList &old_thread_list,
+ lldb_private::ThreadList &new_thread_list);
+
+ lldb_private::ObjectFile *
+ GetCoreObjectFile ()
+ {
+ return m_core_module_sp->GetObjectFile();
+ }
+private:
+ //------------------------------------------------------------------
+ // For ProcessMachCore only
+ //------------------------------------------------------------------
+ typedef lldb_private::Range<uint32_t, uint32_t> FileRange;
+ typedef lldb_private::RangeDataArray<lldb::addr_t, lldb::addr_t, FileRange, 1> VMRangeToFileOffset;
+
+ VMRangeToFileOffset m_core_aranges;
+ lldb::ModuleSP m_core_module_sp;
+ lldb_private::FileSpec m_core_file;
+ lldb::addr_t m_shlib_addr;
+ DISALLOW_COPY_AND_ASSIGN (ProcessMachCore);
+
+};
+
+#endif // liblldb_ProcessMachCore_h_
diff --git a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp
new file mode 100644
index 00000000000..7944996ff6f
--- /dev/null
+++ b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.cpp
@@ -0,0 +1,145 @@
+//===-- ThreadMachCore.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "ThreadMachCore.h"
+
+#include "llvm/Support/MachO.h"
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/State.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Unwind.h"
+#include "lldb/Breakpoint/Watchpoint.h"
+
+#include "ProcessMachCore.h"
+//#include "RegisterContextKDP_arm.h"
+//#include "RegisterContextKDP_i386.h"
+//#include "RegisterContextKDP_x86_64.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Thread Registers
+//----------------------------------------------------------------------
+
+ThreadMachCore::ThreadMachCore (ProcessMachCore &process, lldb::tid_t tid) :
+ Thread(process, tid),
+ m_thread_name (),
+ m_dispatch_queue_name (),
+ m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS)
+{
+}
+
+ThreadMachCore::~ThreadMachCore ()
+{
+ DestroyThread();
+}
+
+const char *
+ThreadMachCore::GetName ()
+{
+ if (m_thread_name.empty())
+ return NULL;
+ return m_thread_name.c_str();
+}
+
+void
+ThreadMachCore::RefreshStateAfterStop()
+{
+ // Invalidate all registers in our register context. We don't set "force" to
+ // true because the stop reply packet might have had some register values
+ // that were expedited and these will already be copied into the register
+ // context by the time this function gets called. The KDPRegisterContext
+ // class has been made smart enough to detect when it needs to invalidate
+ // which registers are valid by putting hooks in the register read and
+ // register supply functions where they check the process stop ID and do
+ // the right thing.
+ const bool force = false;
+ GetRegisterContext()->InvalidateIfNeeded (force);
+}
+
+void
+ThreadMachCore::ClearStackFrames ()
+{
+ Unwind *unwinder = GetUnwinder ();
+ if (unwinder)
+ unwinder->Clear();
+ Thread::ClearStackFrames();
+}
+
+
+bool
+ThreadMachCore::ThreadIDIsValid (lldb::tid_t thread)
+{
+ return thread != 0;
+}
+
+lldb::RegisterContextSP
+ThreadMachCore::GetRegisterContext ()
+{
+ if (m_reg_context_sp.get() == NULL)
+ m_reg_context_sp = CreateRegisterContextForFrame (NULL);
+ return m_reg_context_sp;
+}
+
+lldb::RegisterContextSP
+ThreadMachCore::CreateRegisterContextForFrame (StackFrame *frame)
+{
+ lldb::RegisterContextSP reg_ctx_sp;
+ uint32_t concrete_frame_idx = 0;
+
+ if (frame)
+ concrete_frame_idx = frame->GetConcreteFrameIndex ();
+
+ if (concrete_frame_idx == 0)
+ {
+ ObjectFile *core_objfile = GetMachCoreProcess ().GetCoreObjectFile ();
+ if (core_objfile)
+ reg_ctx_sp = core_objfile->GetThreadContextAtIndex (GetID(), *this);
+ }
+ else if (m_unwinder_ap.get())
+ reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
+ return reg_ctx_sp;
+}
+
+lldb::StopInfoSP
+ThreadMachCore::GetPrivateStopReason ()
+{
+ const uint32_t process_stop_id = GetProcess().GetStopID();
+ if (m_thread_stop_reason_stop_id != process_stop_id ||
+ (m_actual_stop_info_sp && !m_actual_stop_info_sp->IsValid()))
+ {
+ // TODO: can we query the initial state of the thread here?
+ // For now I am just going to pretend that a SIGSTOP happened.
+
+ SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, SIGSTOP));
+
+ // If GetKDPProcess().SetThreadStopInfo() doesn't find a stop reason
+ // for this thread, then m_actual_stop_info_sp will not ever contain
+ // a valid stop reason and the "m_actual_stop_info_sp->IsValid() == false"
+ // check will never be able to tell us if we have the correct stop info
+ // for this thread and we will continually send qThreadStopInfo packets
+ // down to the remote KDP server, so we need to keep our own notion
+ // of the stop ID that m_actual_stop_info_sp is valid for (even if it
+ // contains nothing). We use m_thread_stop_reason_stop_id for this below.
+// m_thread_stop_reason_stop_id = process_stop_id;
+// m_actual_stop_info_sp.reset();
+
+ }
+ return m_actual_stop_info_sp;
+}
+
+
diff --git a/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h
new file mode 100644
index 00000000000..ccb551684fc
--- /dev/null
+++ b/lldb/source/Plugins/Process/mach-core/ThreadMachCore.h
@@ -0,0 +1,98 @@
+//===-- ThreadMachCore.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_ThreadMachCore_h_
+#define liblldb_ThreadMachCore_h_
+
+#include <string>
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+class ProcessMachCore;
+
+class ThreadMachCore : public lldb_private::Thread
+{
+public:
+ ThreadMachCore (ProcessMachCore &process,
+ lldb::tid_t tid);
+
+ virtual
+ ~ThreadMachCore ();
+
+ virtual void
+ RefreshStateAfterStop();
+
+ virtual const char *
+ GetName ();
+
+ virtual lldb::RegisterContextSP
+ GetRegisterContext ();
+
+ virtual lldb::RegisterContextSP
+ CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+ virtual void
+ ClearStackFrames ();
+
+ ProcessMachCore &
+ GetMachCoreProcess ()
+ {
+ return (ProcessMachCore &)m_process;
+ }
+
+ static bool
+ ThreadIDIsValid (lldb::tid_t thread);
+
+ bool
+ ShouldStop (bool &step_more);
+
+ const char *
+ GetBasicInfoAsString ();
+
+ void
+ SetName (const char *name)
+ {
+ if (name && name[0])
+ m_thread_name.assign (name);
+ else
+ m_thread_name.clear();
+ }
+
+ lldb::addr_t
+ GetThreadDispatchQAddr ()
+ {
+ return m_thread_dispatch_qaddr;
+ }
+
+ void
+ SetThreadDispatchQAddr (lldb::addr_t thread_dispatch_qaddr)
+ {
+ m_thread_dispatch_qaddr = thread_dispatch_qaddr;
+ }
+
+protected:
+
+ friend class ProcessMachCore;
+
+ //------------------------------------------------------------------
+ // Member variables.
+ //------------------------------------------------------------------
+ std::string m_thread_name;
+ std::string m_dispatch_queue_name;
+ lldb::addr_t m_thread_dispatch_qaddr;
+ //------------------------------------------------------------------
+ // Member variables.
+ //------------------------------------------------------------------
+
+ virtual lldb::StopInfoSP
+ GetPrivateStopReason ();
+};
+
+#endif // liblldb_ThreadMachCore_h_
diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp
index 862e97312a3..df7c4f8b7ce 100644
--- a/lldb/source/Symbol/ObjectFile.cpp
+++ b/lldb/source/Symbol/ObjectFile.cpp
@@ -156,7 +156,7 @@ ObjectFile::ObjectFile (Module* module,
m_data (),
m_unwind_table (*this),
m_process_wp(),
- m_in_memory (false)
+ m_memory_addr (LLDB_INVALID_ADDRESS)
{
if (file_spec_ptr)
m_file = *file_spec_ptr;
@@ -202,7 +202,7 @@ ObjectFile::ObjectFile (Module* module,
m_data (),
m_unwind_table (*this),
m_process_wp (process_sp),
- m_in_memory (true)
+ m_memory_addr (header_addr)
{
if (header_data_sp)
m_data.SetData (header_data_sp, 0, header_data_sp->GetByteSize());
@@ -382,7 +382,7 @@ ObjectFile::CopyData (off_t offset, size_t length, void *dst) const
size_t
ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void *dst, size_t dst_len) const
{
- if (m_in_memory)
+ if (IsInMemory())
{
ProcessSP process_sp (m_process_wp.lock());
if (process_sp)
@@ -404,7 +404,7 @@ ObjectFile::ReadSectionData (const Section *section, off_t section_offset, void
size_t
ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data) const
{
- if (m_in_memory)
+ if (IsInMemory())
{
ProcessSP process_sp (m_process_wp.lock());
if (process_sp)
@@ -431,7 +431,7 @@ ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data
size_t
ObjectFile::MemoryMapSectionData (const Section *section, DataExtractor& section_data) const
{
- if (m_in_memory)
+ if (IsInMemory())
{
return ReadSectionData (section, section_data);
}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 07e1cdf5241..6ed2b2ac040 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -708,30 +708,39 @@ ProcessInstanceInfoMatch::Clear()
m_match_all_users = false;
}
-Process*
-Process::FindPlugin (Target &target, const char *plugin_name, Listener &listener)
+ProcessSP
+Process::FindPlugin (Target &target, const char *plugin_name, Listener &listener, const FileSpec *crash_file_path)
{
+ ProcessSP process_sp;
ProcessCreateInstance create_callback = NULL;
if (plugin_name)
{
create_callback = PluginManager::GetProcessCreateCallbackForPluginName (plugin_name);
if (create_callback)
{
- std::auto_ptr<Process> debugger_ap(create_callback(target, listener));
- if (debugger_ap->CanDebug(target, true))
- return debugger_ap.release();
+ process_sp = create_callback(target, listener, crash_file_path);
+ if (process_sp)
+ {
+ if (!process_sp->CanDebug(target, true))
+ process_sp.reset();
+ }
}
}
else
{
for (uint32_t idx = 0; (create_callback = PluginManager::GetProcessCreateCallbackAtIndex(idx)) != NULL; ++idx)
{
- std::auto_ptr<Process> debugger_ap(create_callback(target, listener));
- if (debugger_ap->CanDebug(target, false))
- return debugger_ap.release();
+ process_sp = create_callback(target, listener, crash_file_path);
+ if (process_sp)
+ {
+ if (!process_sp->CanDebug(target, false))
+ process_sp.reset();
+ else
+ break;
+ }
}
}
- return NULL;
+ return process_sp;
}
@@ -2328,6 +2337,30 @@ Process::Launch (const ProcessLaunchInfo &launch_info)
return error;
}
+
+Error
+Process::LoadCore ()
+{
+ Error error = DoLoadCore();
+ if (error.Success())
+ {
+ if (PrivateStateThreadIsValid ())
+ ResumePrivateStateThread ();
+ else
+ StartPrivateStateThread ();
+
+ CompleteAttach ();
+ // We successfully loaded a core file, now pretend we stopped so we can
+ // show all of the threads in the core file and explore the crashed
+ // state.
+ SetPrivateState (eStateStopped);
+
+ }
+ return error;
+}
+
+
+
Process::NextEventAction::EventActionResult
Process::AttachCompletionHandler::PerformAction (lldb::EventSP &event_sp)
{
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 48904d6aac6..20b8e938fe1 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -136,10 +136,10 @@ Target::DeleteCurrentProcess ()
}
const lldb::ProcessSP &
-Target::CreateProcess (Listener &listener, const char *plugin_name)
+Target::CreateProcess (Listener &listener, const char *plugin_name, const FileSpec *crash_file)
{
DeleteCurrentProcess ();
- m_process_sp.reset(Process::FindPlugin(*this, plugin_name, listener));
+ m_process_sp = Process::FindPlugin(*this, plugin_name, listener, crash_file);
return m_process_sp;
}
diff --git a/lldb/source/Target/ThreadList.cpp b/lldb/source/Target/ThreadList.cpp
index 240900686d5..e1c38664aa5 100644
--- a/lldb/source/Target/ThreadList.cpp
+++ b/lldb/source/Target/ThreadList.cpp
@@ -77,7 +77,7 @@ ThreadList::SetStopID (uint32_t stop_id)
void
-ThreadList::AddThread (ThreadSP &thread_sp)
+ThreadList::AddThread (const ThreadSP &thread_sp)
{
Mutex::Locker locker(m_threads_mutex);
m_threads.push_back(thread_sp);
diff --git a/lldb/source/lldb.cpp b/lldb/source/lldb.cpp
index 18c9c198d0f..6ee3e1c5d4a 100644
--- a/lldb/source/lldb.cpp
+++ b/lldb/source/lldb.cpp
@@ -51,6 +51,8 @@
#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
#endif
+#include "Plugins/Process/mach-core/ProcessMachCore.h"
+
#if defined (__linux__)
#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
#include "Plugins/Platform/Linux/PlatformLinux.h"
@@ -113,6 +115,7 @@ lldb_private::Initialize ()
ObjectFileMachO::Initialize();
ProcessKDP::Initialize();
ProcessGDBRemote::Initialize();
+ ProcessMachCore::Initialize();
SymbolVendorMacOSX::Initialize();
PlatformMacOSX::Initialize();
PlatformRemoteiOS::Initialize();
@@ -183,6 +186,7 @@ lldb_private::Terminate ()
AppleObjCRuntimeV1::Terminate();
ObjectContainerUniversalMachO::Terminate();
ObjectFileMachO::Terminate();
+ ProcessMachCore::Terminate();
ProcessKDP::Terminate();
ProcessGDBRemote::Terminate();
SymbolVendorMacOSX::Terminate();
OpenPOWER on IntegriCloud